diff --git a/.Icon.ico-autosave.kra b/.Icon.ico-autosave.kra new file mode 100644 index 0000000..fadfcfb Binary files /dev/null and b/.Icon.ico-autosave.kra differ diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..035c2f8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,11 @@ +ColumnLimit: 120 +PointerAlignment: Left +ReferenceAlignment: Left +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +CommentPragmas: '^' +BreakBeforeBraces: Allman +NamespaceIndentation: All +FixNamespaceComments: false +IndentCaseLabels: true +IndentPPDirectives: BeforeHash \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4a0b47c..f0a7d48 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,8 @@ release/ packed/ vcpkg_installed/ out/ -include/imgui/ -include/glm/ -include/tinyxml2 +external/ workshop/resources +cmake-build-debug/ .vs/ +.idea/ diff --git a/.gitmodules b/.gitmodules index 8b36230..7172566 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +1,22 @@ -[submodule "include/imgui"] - path = include/imgui +[submodule "external/glm"] + path = external/glm + url = https://github.com/g-truc/glm +[submodule "external/imgui"] + path = external/imgui url = https://github.com/ocornut/imgui branch = docking -[submodule "include/glm"] - path = include/glm - url = https://github.com/g-truc/glm -[submodule "include/tinyxml2"] - path = include/tinyxml2 +[submodule "external/tinyxml2"] + path = external/tinyxml2 url = https://github.com/leethomason/tinyxml2 +[submodule "external/SDL"] + path = external/SDL + url = https://github.com/libsdl-org/SDL.git +[submodule "external/lunasvg"] + path = external/lunasvg + url = https://github.com/sammycage/lunasvg +[submodule "external/SDL_mixer"] + path = external/SDL_mixer + url = https://github.com/libsdl-org/SDL_mixer +[submodule "external/libxm"] + path = external/libxm + url = https://github.com/Artefact2/libxm diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..71afeef --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug ANM2Ed", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/anm2ed", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing" + }, + { + "description": "Set disassembly flavor to Intel", + "text": "-gdb-set disassembly-flavor intel" + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..dff56b4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,17 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "cmake --build build --target anm2ed", + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [ + "$gcc" + ] + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 09e09cd..1781c6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,75 +1,159 @@ -cmake_minimum_required(VERSION 3.15) - -if(WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) - set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") -endif() - +cmake_minimum_required(VERSION 3.30) project(anm2ed CXX) -find_package(SDL3 REQUIRED) -find_package(OpenGL REQUIRED) +if (WIN32 AND DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE) + set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") +endif () -set(GLAD_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp -) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +if (CMAKE_EXPORT_COMPILE_COMMANDS) + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink + ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json + ) +endif () + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +set(SDL_STATIC ON CACHE BOOL "" FORCE) +set(SDL_SHARED OFF CACHE BOOL "" FORCE) +set(SDL_HAPTIC OFF CACHE BOOL "" FORCE) +set(SDL_SENSOR OFF CACHE BOOL "" FORCE) +set(SDL_HIDAPI OFF CACHE BOOL "" FORCE) +set(SDL_CAMERA OFF CACHE BOOL "" FORCE) +set(SDL_TRAY OFF CACHE BOOL "" FORCE) +add_subdirectory(external/SDL EXCLUDE_FROM_ALL) + +set(SDLMIXER_DEPS_SHARED OFF CACHE BOOL "" FORCE) +set(SDLMIXER_FLAC_LIBFLAC OFF CACHE BOOL "" FORCE) +set(SDLMIXER_GME OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MOD_XMP OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MP3_MPG123 OFF CACHE BOOL "" FORCE) +set(SDLMIXER_MIDI_FLUIDSYNTH OFF CACHE BOOL "" FORCE) +set(SDLMIXER_OPUS OFF CACHE BOOL "" FORCE) +set(SDLMIXER_VORBIS_VORBISFILE OFF CACHE BOOL "" FORCE) +set(SDLMIXER_VORBIS_TREMOR OFF CACHE BOOL "" FORCE) +set(SDLMIXER_WAVPACK OFF CACHE BOOL "" FORCE) +set(SDLMIXER_TEST OFF CACHE BOOL "" FORCE) +set(SDLMIXER_INSTALL OFF CACHE BOOL "" FORCE) +add_subdirectory(external/SDL_mixer EXCLUDE_FROM_ALL) + +add_subdirectory(external/lunasvg) + +set(GLAD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/include/glad/glad.cpp) set(IMGUI_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_draw.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_widgets.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/imgui_tables.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/backends/imgui_impl_sdl3.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui/backends/imgui_impl_opengl3.cpp + external/imgui/imgui.cpp + external/imgui/imgui_draw.cpp + external/imgui/imgui_widgets.cpp + external/imgui/imgui_tables.cpp + external/imgui/backends/imgui_impl_sdl3.cpp + external/imgui/backends/imgui_impl_opengl3.cpp ) -set(TINYXML2_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/include/tinyxml2/tinyxml2.cpp -) +set(TINYXML2_SRC external/tinyxml2/tinyxml2.cpp) -file(GLOB PROJECT_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h +file(GLOB PROJECT_SRC CONFIGURE_DEPENDS + src/anm2/*.cpp + src/anm2/*.h + src/resource/*.cpp + src/resource/*.h + src/imgui/*.cpp + src/imgui/*.h + src/imgui/window/*.cpp + src/imgui/window/*.h + src/util/*.cpp + src/util/*.h + src/window/*.cpp + src/window/*.h + src/*.cpp + src/*.h ) add_executable(${PROJECT_NAME} - ${GLAD_SRC} - ${IMGUI_SRC} - ${TINYXML2_SRC} - ${PROJECT_SRC} + ${GLAD_SRC} + ${IMGUI_SRC} + ${TINYXML2_SRC} + ${PROJECT_SRC} ) -if(WIN32) - enable_language(RC) - target_sources(${PROJECT_NAME} PRIVATE assets/Icon.rc) - set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) -endif() -target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) +if (WIN32) + enable_language(RC) + target_sources(${PROJECT_NAME} PRIVATE Icon.rc) + set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) + + set_property(TARGET ${PROJECT_NAME} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + + target_compile_options(${PROJECT_NAME} PRIVATE /EHsc) + target_link_options(${PROJECT_NAME} PRIVATE /STACK:0xffffff) +else () + target_compile_options(${PROJECT_NAME} PRIVATE + -Wall -Wextra -pedantic + ) + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_definitions(${PROJECT_NAME} PRIVATE DEBUG) + target_compile_options(${PROJECT_NAME} PRIVATE -O0 -pg) + else () + set(CMAKE_BUILD_TYPE "Release") + target_compile_options(${PROJECT_NAME} PRIVATE -Os) + endif () + + target_link_libraries(${PROJECT_NAME} PRIVATE m) +endif () + +target_compile_definitions(${PROJECT_NAME} PRIVATE + IMGUI_DISABLE_OBSOLETE_FUNCTIONS + IMGUI_DEBUG_PARANOID + IMGUI_ENABLE_DOCKING +) target_include_directories(${PROJECT_NAME} PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/include/glad - ${CMAKE_CURRENT_SOURCE_DIR}/include/imgui - ${CMAKE_CURRENT_SOURCE_DIR}/include/tinyxml2 - ${CMAKE_CURRENT_SOURCE_DIR}/src + external + external/imgui + external/glm + external/tinyxml2 + external/lunasvg + external/SDL + external/SDL_mixer + include + include/glad + src + src/imgui + src/resource + src/util ) -if(MSVC) - target_compile_options(${PROJECT_NAME} PRIVATE /std:c++latest /EHsc) - target_link_options(${PROJECT_NAME} PRIVATE /STACK:0xffffff) -else() - target_compile_options(${PROJECT_NAME} PRIVATE -O2 -std=c++23 -Wall -Wextra -pedantic -fmax-errors=1) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - target_compile_options(${PROJECT_NAME} PRIVATE -DDEBUG -g) - else() - set(CMAKE_BUILD_TYPE "Release") - endif() - target_link_libraries(${PROJECT_NAME} PRIVATE m) -endif() +target_link_libraries(${PROJECT_NAME} PRIVATE GL SDL3-static SDL3_mixer::SDL3_mixer lunasvg) -target_link_libraries(${PROJECT_NAME} PRIVATE OpenGL::GL SDL3::SDL3) +message(STATUS "System: ${CMAKE_SYSTEM_NAME}") +message(STATUS "Project: ${PROJECT_NAME}") +message(STATUS "Compiler: ${CMAKE_CXX_COMPILER}") -message("System: ${CMAKE_SYSTEM_NAME}") -message("Project: ${PROJECT_NAME}") -message("Build: ${CMAKE_BUILD_TYPE}") \ No newline at end of file +get_target_property(PROJECT_COMPILE_OPTIONS ${PROJECT_NAME} COMPILE_OPTIONS) +if (NOT PROJECT_COMPILE_OPTIONS) + set(PROJECT_COMPILE_OPTIONS "") +endif () + +string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_UPPER) +set(EFFECTIVE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +if (BUILD_TYPE_UPPER) + set(CONFIG_FLAGS_VAR "CMAKE_CXX_FLAGS_${BUILD_TYPE_UPPER}") + if (DEFINED ${CONFIG_FLAGS_VAR}) + string(APPEND EFFECTIVE_CXX_FLAGS " ${${CONFIG_FLAGS_VAR}}") + endif () +endif () +string(STRIP "${EFFECTIVE_CXX_FLAGS}" EFFECTIVE_CXX_FLAGS) +if (EFFECTIVE_CXX_FLAGS STREQUAL "") + set(EFFECTIVE_CXX_FLAGS "") +endif () + +message(STATUS "Compiler Flags: ${EFFECTIVE_CXX_FLAGS}") +message(STATUS "Target Compile Options: ${PROJECT_COMPILE_OPTIONS}") +message(STATUS "Build: ${CMAKE_BUILD_TYPE}") diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 137e083..0000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - }, - { - "name": "x64-Release", - "generator": "Ninja", - "configurationType": "Release", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\build\\${name}", - "installRoot": "${projectDir}\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] -} \ No newline at end of file diff --git a/assets/Icon.ico b/Icon.ico similarity index 100% rename from assets/Icon.ico rename to Icon.ico diff --git a/assets/Icon.rc b/Icon.rc similarity index 100% rename from assets/Icon.rc rename to Icon.rc diff --git a/assets/atlas.png b/assets/atlas.png deleted file mode 100644 index 630a225..0000000 Binary files a/assets/atlas.png and /dev/null differ diff --git a/assets/atlas_data_write.sh b/assets/atlas_data_write.sh deleted file mode 100755 index 1cf391f..0000000 --- a/assets/atlas_data_write.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -INPUT="atlas.png" -OUTPUT="../src/PACKED.h" -TMP="atlas.bytes" - -# Ensure deps -command -v optipng >/dev/null 2>&1 || { echo "error: optipng not found in PATH" >&2; exit 1; } -command -v xxd >/dev/null 2>&1 || { echo "error: xxd not found in PATH" >&2; exit 1; } - -# 1) Optimize PNG in place -optipng -o7 "$INPUT" >/dev/null - -# 2) Extract ONLY the bytes from xxd -i (between '= {' and '};') -# Using awk avoids the earlier '{' vs '= {' mismatch bug. -xxd -i "$INPUT" \ - | awk ' - /= *\{/ {inside=1; next} - inside && /};/ {inside=0; exit} - inside {print} - ' > "$TMP" - -# Sanity check: make sure we got something -if ! [ -s "$TMP" ]; then - echo "error: failed to extract bytes from xxd output" >&2 - exit 1 -fi - -# 3) Replace ONLY the bytes inside TEXTURE_ATLAS[] initializer -# - Find the exact declaration line for TEXTURE_ATLAS -# - Print that line -# - On the following line with just '{', print it, then insert bytes, -# then skip everything until the matching '};' and print that once. -awk -v tmpfile="$TMP" ' - BEGIN { state=0 } # 0=normal, 1=after decl waiting for {, 2=skipping old bytes until }; - - # Match the TEXTURE_ATLAS declaration line precisely - $0 ~ /^[[:space:]]*const[[:space:]]+u8[[:space:]]+TEXTURE_ATLAS\[\][[:space:]]*=/ { - print; state=1; next - } - - # After the decl, the next line with a lone "{" starts the initializer - state==1 && $0 ~ /^[[:space:]]*{[[:space:]]*$/ { - print # print the opening brace line - while ((getline line < tmpfile) > 0) print line # insert fresh bytes - close(tmpfile) - state=2 # now skip old initializer content until we hit the closing "};" - next - } - - # While skipping, suppress lines until the closing "};", which we reprint once - state==2 { - if ($0 ~ /^[[:space:]]*};[[:space:]]*$/) { - print # print the closing brace+semicolon - state=0 - } - next - } - - # Default: pass through unchanged - { print } -' "$OUTPUT" > "$OUTPUT.tmp" && mv "$OUTPUT.tmp" "$OUTPUT" - -rm -f "$TMP" -echo "Updated $OUTPUT with optimized bytes from $INPUT." diff --git a/compile_commands.json b/compile_commands.json new file mode 120000 index 0000000..5e95284 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1 @@ +/home/anon/sda/Personal/Repos/anm2ed/build/compile_commands.json \ No newline at end of file diff --git a/external/SDL_mixer b/external/SDL_mixer new file mode 160000 index 0000000..8c516fc --- /dev/null +++ b/external/SDL_mixer @@ -0,0 +1 @@ +Subproject commit 8c516fcd2eca48262188426fbe75365ba4326346 diff --git a/include/glm b/external/glm similarity index 100% rename from include/glm rename to external/glm diff --git a/external/imgui b/external/imgui new file mode 160000 index 0000000..0955992 --- /dev/null +++ b/external/imgui @@ -0,0 +1 @@ +Subproject commit 0955992dd9dbfdff2b854efcb2a559265afa7923 diff --git a/external/libxm b/external/libxm new file mode 160000 index 0000000..9f599c4 --- /dev/null +++ b/external/libxm @@ -0,0 +1 @@ +Subproject commit 9f599c4dd4079700e2d9b8af62dc1ab8d76808f5 diff --git a/external/tinyxml2 b/external/tinyxml2 new file mode 160000 index 0000000..36ff404 --- /dev/null +++ b/external/tinyxml2 @@ -0,0 +1 @@ +Subproject commit 36ff404c346acadd8a42c135f096ebd5437610b1 diff --git a/include/imgui b/include/imgui deleted file mode 160000 index d896eab..0000000 --- a/include/imgui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d896eab16620f80e3cae9b164eb62f71b47f6e45 diff --git a/include/nanosvg.h b/include/nanosvg.h new file mode 100644 index 0000000..a3dba05 --- /dev/null +++ b/include/nanosvg.h @@ -0,0 +1,3121 @@ +/* + * Copyright (c) 2013-14 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. + * + * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example + * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/) + * + * Arc calculation code based on canvg (https://code.google.com/p/canvg/) + * + * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + * + */ + +#ifndef NANOSVG_H +#define NANOSVG_H + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. +// +// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. +// +// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! +// +// The shapes in the SVG images are transformed by the viewBox and converted to specified units. +// That is, you should get the same looking data as your designed in your favorite app. +// +// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose +// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. +// +// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. +// DPI (dots-per-inch) controls how the unit conversion is done. +// +// If you don't know or care about the units stuff, "px" and 96 should get you going. + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + printf("size: %f x %f\n", image->width, image->height); + // Use... + for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) { + for (NSVGpath *path = shape->paths; path != NULL; path = path->next) { + for (int i = 0; i < path->npts-1; i += 3) { + float* p = &path->pts[i*2]; + drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]); + } + } + } + // Delete + nsvgDelete(image); +*/ + +enum NSVGpaintType { NSVG_PAINT_UNDEF = -1, NSVG_PAINT_NONE = 0, NSVG_PAINT_COLOR = 1, NSVG_PAINT_LINEAR_GRADIENT = 2, NSVG_PAINT_RADIAL_GRADIENT = 3 }; + +enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, NSVG_SPREAD_REPEAT = 2 }; + +enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, NSVG_JOIN_BEVEL = 2 }; + +enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, NSVG_CAP_SQUARE = 2 }; + +enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, NSVG_FILLRULE_EVENODD = 1 }; + +enum NSVGflags { NSVG_FLAGS_VISIBLE = 0x01 }; + +enum NSVGpaintOrder { + NSVG_PAINT_FILL = 0x00, + NSVG_PAINT_MARKERS = 0x01, + NSVG_PAINT_STROKE = 0x02, +}; + +typedef struct NSVGgradientStop { + unsigned int color; + float offset; +} NSVGgradientStop; + +typedef struct NSVGgradient { + float xform[6]; + char spread; + float fx, fy; + int nstops; + NSVGgradientStop stops[1]; +} NSVGgradient; + +typedef struct NSVGpaint { + signed char type; + union { + unsigned int color; + NSVGgradient* gradient; + }; +} NSVGpaint; + +typedef struct NSVGpath { + float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... + int npts; // Total number of bezier points. + char closed; // Flag indicating if shapes should be treated as closed. + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + struct NSVGpath* next; // Pointer to next path, or NULL if last element. +} NSVGpath; + +typedef struct NSVGshape { + char id[64]; // Optional 'id' attr of the shape or its group + NSVGpaint fill; // Fill paint + NSVGpaint stroke; // Stroke paint + float opacity; // Opacity of the shape. + float strokeWidth; // Stroke width (scaled). + float strokeDashOffset; // Stroke dash offset (scaled). + float strokeDashArray[8]; // Stroke dash array (scaled). + char strokeDashCount; // Number of dash values in dash array. + char strokeLineJoin; // Stroke join type. + char strokeLineCap; // Stroke cap type. + float miterLimit; // Miter limit + char fillRule; // Fill rule, see NSVGfillRule. + unsigned char paintOrder; // Encoded paint order (3×2-bit fields) see NSVGpaintOrder + unsigned char flags; // Logical or of NSVG_FLAGS_* flags + float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + char fillGradient[64]; // Optional 'id' of fill gradient + char strokeGradient[64]; // Optional 'id' of stroke gradient + float xform[6]; // Root transformation for fill/stroke gradient + NSVGpath* paths; // Linked list of paths in the image. + struct NSVGshape* next; // Pointer to next shape, or NULL if last element. +} NSVGshape; + +typedef struct NSVGimage { + float width; // Width of the image. + float height; // Height of the image. + NSVGshape* shapes; // Linked list of shapes in the image. +} NSVGimage; + +// Parses SVG file from a file, returns SVG image as paths. +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); + +// Parses SVG file from a null terminated string, returns SVG image as paths. +// Important note: changes the string. +NSVGimage* nsvgParse(char* input, const char* units, float dpi); + +// Duplicates a path. +NSVGpath* nsvgDuplicatePath(NSVGpath* p); + +// Deletes an image. +void nsvgDelete(NSVGimage* image); + +#ifndef NANOSVG_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVG_IMPLEMENTATION + +#include +#include +#include +#include + +#define NSVG_PI (3.14159265358979323846264338327f) +#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. + +#define NSVG_ALIGN_MIN 0 +#define NSVG_ALIGN_MID 1 +#define NSVG_ALIGN_MAX 2 +#define NSVG_ALIGN_NONE 0 +#define NSVG_ALIGN_MEET 1 +#define NSVG_ALIGN_SLICE 2 + +#define NSVG_NOTUSED(v) \ + do { \ + (void)(1 ? (void)0 : ((void)(v))); \ + } while (0) +#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) + +#ifdef _MSC_VER +#pragma warning(disable : 4996) // Switch off security warnings +#pragma warning(disable : 4100) // Switch off unreferenced formal parameter warnings +#ifdef __cplusplus +#define NSVG_INLINE inline +#else +#define NSVG_INLINE +#endif +#else +#define NSVG_INLINE inline +#endif + +static int nsvg__isspace(char c) { return strchr(" \t\n\v\f\r", c) != 0; } + +static int nsvg__isdigit(char c) { return c >= '0' && c <= '9'; } + +static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } +static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } + +// Simple XML parser + +#define NSVG_XML_TAG 1 +#define NSVG_XML_CONTENT 2 +#define NSVG_XML_MAX_ATTRIBS 256 + +static void nsvg__parseContent(char* s, void (*contentCb)(void* ud, const char* s), void* ud) { + // Trim start white spaces + while (*s && nsvg__isspace(*s)) + s++; + if (!*s) + return; + + if (contentCb) + (*contentCb)(ud, s); +} + +static void nsvg__parseElement(char* s, void (*startelCb)(void* ud, const char* el, const char** attr), void (*endelCb)(void* ud, const char* el), void* ud) { + const char* attr[NSVG_XML_MAX_ATTRIBS]; + int nattr = 0; + char* name; + int start = 0; + int end = 0; + char quote; + + // Skip white space after the '<' + while (*s && nsvg__isspace(*s)) + s++; + + // Check if the tag is end tag + if (*s == '/') { + s++; + end = 1; + } else { + start = 1; + } + + // Skip comments, data and preprocessor stuff. + if (!*s || *s == '?' || *s == '!') + return; + + // Get tag name + name = s; + while (*s && !nsvg__isspace(*s)) + s++; + if (*s) { + *s++ = '\0'; + } + + // Get attribs + while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS - 3) { + char* name = NULL; + char* value = NULL; + + // Skip white space before the attrib name + while (*s && nsvg__isspace(*s)) + s++; + if (!*s) + break; + if (*s == '/') { + end = 1; + break; + } + name = s; + // Find end of the attrib name. + while (*s && !nsvg__isspace(*s) && *s != '=') + s++; + if (*s) { + *s++ = '\0'; + } + // Skip until the beginning of the value. + while (*s && *s != '\"' && *s != '\'') + s++; + if (!*s) + break; + quote = *s; + s++; + // Store value and find the end of it. + value = s; + while (*s && *s != quote) + s++; + if (*s) { + *s++ = '\0'; + } + + // Store only well formed attributes + if (name && value) { + attr[nattr++] = name; + attr[nattr++] = value; + } + } + + // List terminator + attr[nattr++] = 0; + attr[nattr++] = 0; + + // Call callbacks. + if (start && startelCb) + (*startelCb)(ud, name, attr); + if (end && endelCb) + (*endelCb)(ud, name); +} + +int nsvg__parseXML(char* input, void (*startelCb)(void* ud, const char* el, const char** attr), void (*endelCb)(void* ud, const char* el), + void (*contentCb)(void* ud, const char* s), void* ud) { + char* s = input; + char* mark = s; + int state = NSVG_XML_CONTENT; + while (*s) { + if (*s == '<' && state == NSVG_XML_CONTENT) { + // Start of a tag + *s++ = '\0'; + nsvg__parseContent(mark, contentCb, ud); + mark = s; + state = NSVG_XML_TAG; + } else if (*s == '>' && state == NSVG_XML_TAG) { + // Start of a content or new tag. + *s++ = '\0'; + nsvg__parseElement(mark, startelCb, endelCb, ud); + mark = s; + state = NSVG_XML_CONTENT; + } else { + s++; + } + } + + return 1; +} + +/* Simple SVG parser. */ + +#define NSVG_MAX_ATTR 128 + +enum NSVGgradientUnits { NSVG_USER_SPACE = 0, NSVG_OBJECT_SPACE = 1 }; + +#define NSVG_MAX_DASHES 8 + +enum NSVGunits { + NSVG_UNITS_USER, + NSVG_UNITS_PX, + NSVG_UNITS_PT, + NSVG_UNITS_PC, + NSVG_UNITS_MM, + NSVG_UNITS_CM, + NSVG_UNITS_IN, + NSVG_UNITS_PERCENT, + NSVG_UNITS_EM, + NSVG_UNITS_EX +}; + +typedef struct NSVGcoordinate { + float value; + int units; +} NSVGcoordinate; + +typedef struct NSVGlinearData { + NSVGcoordinate x1, y1, x2, y2; +} NSVGlinearData; + +typedef struct NSVGradialData { + NSVGcoordinate cx, cy, r, fx, fy; +} NSVGradialData; + +typedef struct NSVGgradientData { + char id[64]; + char ref[64]; + signed char type; + union { + NSVGlinearData linear; + NSVGradialData radial; + }; + char spread; + char units; + float xform[6]; + int nstops; + NSVGgradientStop* stops; + struct NSVGgradientData* next; +} NSVGgradientData; + +typedef struct NSVGattrib { + char id[64]; + float xform[6]; + unsigned int fillColor; + unsigned int strokeColor; + float opacity; + float fillOpacity; + float strokeOpacity; + char fillGradient[64]; + char strokeGradient[64]; + float strokeWidth; + float strokeDashOffset; + float strokeDashArray[NSVG_MAX_DASHES]; + int strokeDashCount; + char strokeLineJoin; + char strokeLineCap; + float miterLimit; + char fillRule; + float fontSize; + unsigned int stopColor; + float stopOpacity; + float stopOffset; + char hasFill; + char hasStroke; + char visible; + unsigned char paintOrder; +} NSVGattrib; + +typedef struct NSVGparser { + NSVGattrib attr[NSVG_MAX_ATTR]; + int attrHead; + float* pts; + int npts; + int cpts; + NSVGpath* plist; + NSVGimage* image; + NSVGgradientData* gradients; + NSVGshape* shapesTail; + float viewMinx, viewMiny, viewWidth, viewHeight; + int alignX, alignY, alignType; + float dpi; + char pathFlag; + char defsFlag; +} NSVGparser; + +static void nsvg__xformIdentity(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; +} + +static void nsvg__xformSetTranslation(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; +} + +static void nsvg__xformSetScale(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; +} + +static void nsvg__xformSetSkewX(float* t, float a) { + t[0] = 1.0f; + t[1] = 0.0f; + t[2] = tanf(a); + t[3] = 1.0f; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetSkewY(float* t, float a) { + t[0] = 1.0f; + t[1] = tanf(a); + t[2] = 0.0f; + t[3] = 1.0f; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformSetRotation(float* t, float a) { + float cs = cosf(a), sn = sinf(a); + t[0] = cs; + t[1] = sn; + t[2] = -sn; + t[3] = cs; + t[4] = 0.0f; + t[5] = 0.0f; +} + +static void nsvg__xformMultiply(float* t, 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; +} + +static void nsvg__xformInverse(float* inv, float* t) { + double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1]; + if (det > -1e-6 && det < 1e-6) { + nsvg__xformIdentity(t); + return; + } + 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); +} + +static void nsvg__xformPremultiply(float* t, float* s) { + float s2[6]; + memcpy(s2, s, sizeof(float) * 6); + nsvg__xformMultiply(s2, t); + memcpy(t, s2, sizeof(float) * 6); +} + +static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t) { + *dx = x * t[0] + y * t[2] + t[4]; + *dy = x * t[1] + y * t[3] + t[5]; +} + +static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t) { + *dx = x * t[0] + y * t[2]; + *dy = x * t[1] + y * t[3]; +} + +#define NSVG_EPSILON (1e-12) + +static int nsvg__ptInBounds(float* pt, float* bounds) { return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3]; } + +static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3) { + double it = 1.0 - t; + return it * it * it * p0 + 3.0 * it * it * t * p1 + 3.0 * it * t * t * p2 + t * t * t * p3; +} + +static void nsvg__curveBounds(float* bounds, float* curve) { + int i, j, count; + double roots[2], a, b, c, b2ac, t, v; + float* v0 = &curve[0]; + float* v1 = &curve[2]; + float* v2 = &curve[4]; + float* v3 = &curve[6]; + + // Start the bounding box by end points + bounds[0] = nsvg__minf(v0[0], v3[0]); + bounds[1] = nsvg__minf(v0[1], v3[1]); + bounds[2] = nsvg__maxf(v0[0], v3[0]); + bounds[3] = nsvg__maxf(v0[1], v3[1]); + + // Bezier curve fits inside the convex hull of it's control points. + // If control points are inside the bounds, we're done. + if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) + return; + + // Add bezier curve inflection points in X and Y. + for (i = 0; i < 2; i++) { + a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; + b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; + c = 3.0 * v1[i] - 3.0 * v0[i]; + count = 0; + if (fabs(a) < NSVG_EPSILON) { + if (fabs(b) > NSVG_EPSILON) { + t = -c / b; + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + } + } else { + b2ac = b * b - 4.0 * c * a; + if (b2ac > NSVG_EPSILON) { + t = (-b + sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + t = (-b - sqrt(b2ac)) / (2.0 * a); + if (t > NSVG_EPSILON && t < 1.0 - NSVG_EPSILON) + roots[count++] = t; + } + } + for (j = 0; j < count; j++) { + v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]); + bounds[0 + i] = nsvg__minf(bounds[0 + i], (float)v); + bounds[2 + i] = nsvg__maxf(bounds[2 + i], (float)v); + } + } +} + +static unsigned char nsvg__encodePaintOrder(enum NSVGpaintOrder a, enum NSVGpaintOrder b, enum NSVGpaintOrder c) { + return (a & 0x03) | ((b & 0x03) << 2) | ((c & 0x03) << 4); +} + +static NSVGparser* nsvg__createParser(void) { + NSVGparser* p; + p = (NSVGparser*)malloc(sizeof(NSVGparser)); + if (p == NULL) + goto error; + memset(p, 0, sizeof(NSVGparser)); + + p->image = (NSVGimage*)malloc(sizeof(NSVGimage)); + if (p->image == NULL) + goto error; + memset(p->image, 0, sizeof(NSVGimage)); + + // Init style + nsvg__xformIdentity(p->attr[0].xform); + memset(p->attr[0].id, 0, sizeof p->attr[0].id); + p->attr[0].fillColor = NSVG_RGB(0, 0, 0); + p->attr[0].strokeColor = NSVG_RGB(0, 0, 0); + p->attr[0].opacity = 1; + p->attr[0].fillOpacity = 1; + p->attr[0].strokeOpacity = 1; + p->attr[0].stopOpacity = 1; + p->attr[0].strokeWidth = 1; + p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; + p->attr[0].strokeLineCap = NSVG_CAP_BUTT; + p->attr[0].miterLimit = 4; + p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; + p->attr[0].hasFill = 1; + p->attr[0].visible = 1; + p->attr[0].paintOrder = nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); + + return p; + +error: + if (p) { + if (p->image) + free(p->image); + free(p); + } + return NULL; +} + +static void nsvg__deletePaths(NSVGpath* path) { + while (path) { + NSVGpath* next = path->next; + if (path->pts != NULL) + free(path->pts); + free(path); + path = next; + } +} + +static void nsvg__deletePaint(NSVGpaint* paint) { + if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT) + free(paint->gradient); +} + +static void nsvg__deleteGradientData(NSVGgradientData* grad) { + NSVGgradientData* next; + while (grad != NULL) { + next = grad->next; + free(grad->stops); + free(grad); + grad = next; + } +} + +static void nsvg__deleteParser(NSVGparser* p) { + if (p != NULL) { + nsvg__deletePaths(p->plist); + nsvg__deleteGradientData(p->gradients); + nsvgDelete(p->image); + free(p->pts); + free(p); + } +} + +static void nsvg__resetPath(NSVGparser* p) { p->npts = 0; } + +static void nsvg__addPoint(NSVGparser* p, float x, float y) { + if (p->npts + 1 > p->cpts) { + p->cpts = p->cpts ? p->cpts * 2 : 8; + p->pts = (float*)realloc(p->pts, p->cpts * 2 * sizeof(float)); + if (!p->pts) + return; + } + p->pts[p->npts * 2 + 0] = x; + p->pts[p->npts * 2 + 1] = y; + p->npts++; +} + +static void nsvg__moveTo(NSVGparser* p, float x, float y) { + if (p->npts > 0) { + p->pts[(p->npts - 1) * 2 + 0] = x; + p->pts[(p->npts - 1) * 2 + 1] = y; + } else { + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__lineTo(NSVGparser* p, float x, float y) { + float px, py, dx, dy; + if (p->npts > 0) { + px = p->pts[(p->npts - 1) * 2 + 0]; + py = p->pts[(p->npts - 1) * 2 + 1]; + dx = x - px; + dy = y - py; + nsvg__addPoint(p, px + dx / 3.0f, py + dy / 3.0f); + nsvg__addPoint(p, x - dx / 3.0f, y - dy / 3.0f); + nsvg__addPoint(p, x, y); + } +} + +static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) { + if (p->npts > 0) { + nsvg__addPoint(p, cpx1, cpy1); + nsvg__addPoint(p, cpx2, cpy2); + nsvg__addPoint(p, x, y); + } +} + +static NSVGattrib* nsvg__getAttr(NSVGparser* p) { return &p->attr[p->attrHead]; } + +static void nsvg__pushAttr(NSVGparser* p) { + if (p->attrHead < NSVG_MAX_ATTR - 1) { + p->attrHead++; + memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead - 1], sizeof(NSVGattrib)); + } +} + +static void nsvg__popAttr(NSVGparser* p) { + if (p->attrHead > 0) + p->attrHead--; +} + +static float nsvg__actualOrigX(NSVGparser* p) { return p->viewMinx; } + +static float nsvg__actualOrigY(NSVGparser* p) { return p->viewMiny; } + +static float nsvg__actualWidth(NSVGparser* p) { return p->viewWidth; } + +static float nsvg__actualHeight(NSVGparser* p) { return p->viewHeight; } + +static float nsvg__actualLength(NSVGparser* p) { + float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p); + return sqrtf(w * w + h * h) / sqrtf(2.0f); +} + +static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length) { + NSVGattrib* attr = nsvg__getAttr(p); + switch (c.units) { + case NSVG_UNITS_USER: + return c.value; + case NSVG_UNITS_PX: + return c.value; + case NSVG_UNITS_PT: + return c.value / 72.0f * p->dpi; + case NSVG_UNITS_PC: + return c.value / 6.0f * p->dpi; + case NSVG_UNITS_MM: + return c.value / 25.4f * p->dpi; + case NSVG_UNITS_CM: + return c.value / 2.54f * p->dpi; + case NSVG_UNITS_IN: + return c.value * p->dpi; + case NSVG_UNITS_EM: + return c.value * attr->fontSize; + case NSVG_UNITS_EX: + return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. + case NSVG_UNITS_PERCENT: + return orig + c.value / 100.0f * length; + default: + return c.value; + } + return c.value; +} + +static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id) { + NSVGgradientData* grad = p->gradients; + if (id == NULL || *id == '\0') + return NULL; + while (grad != NULL) { + if (strcmp(grad->id, id) == 0) + return grad; + grad = grad->next; + } + return NULL; +} + +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float* xform, signed char* paintType) { + NSVGgradientData* data = NULL; + NSVGgradientData* ref = NULL; + NSVGgradientStop* stops = NULL; + NSVGgradient* grad; + float ox, oy, sw, sh, sl; + int nstops = 0; + int refIter; + + data = nsvg__findGradientData(p, id); + if (data == NULL) + return NULL; + + // TODO: use ref to fill in all unset values too. + ref = data; + refIter = 0; + while (ref != NULL) { + NSVGgradientData* nextRef = NULL; + if (stops == NULL && ref->stops != NULL) { + stops = ref->stops; + nstops = ref->nstops; + break; + } + nextRef = nsvg__findGradientData(p, ref->ref); + if (nextRef == ref) + break; // prevent infite loops on malformed data + ref = nextRef; + refIter++; + if (refIter > 32) + break; // prevent infite loops on malformed data + } + if (stops == NULL) + return NULL; + + grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop) * (nstops - 1)); + if (grad == NULL) + return NULL; + + // The shape width and height. + if (data->units == NSVG_OBJECT_SPACE) { + ox = localBounds[0]; + oy = localBounds[1]; + sw = localBounds[2] - localBounds[0]; + sh = localBounds[3] - localBounds[1]; + } else { + ox = nsvg__actualOrigX(p); + oy = nsvg__actualOrigY(p); + sw = nsvg__actualWidth(p); + sh = nsvg__actualHeight(p); + } + sl = sqrtf(sw * sw + sh * sh) / sqrtf(2.0f); + + if (data->type == NSVG_PAINT_LINEAR_GRADIENT) { + float x1, y1, x2, y2, dx, dy; + x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); + y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); + x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); + y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); + // Calculate transform aligned to the line + dx = x2 - x1; + dy = y2 - y1; + grad->xform[0] = dy; + grad->xform[1] = -dx; + grad->xform[2] = dx; + grad->xform[3] = dy; + grad->xform[4] = x1; + grad->xform[5] = y1; + } else { + float cx, cy, fx, fy, r; + cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); + cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); + fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); + fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); + r = nsvg__convertToPixels(p, data->radial.r, 0, sl); + // Calculate transform aligned to the circle + grad->xform[0] = r; + grad->xform[1] = 0; + grad->xform[2] = 0; + grad->xform[3] = r; + grad->xform[4] = cx; + grad->xform[5] = cy; + grad->fx = fx / r; + grad->fy = fy / r; + } + + nsvg__xformMultiply(grad->xform, data->xform); + nsvg__xformMultiply(grad->xform, xform); + + grad->spread = data->spread; + memcpy(grad->stops, stops, nstops * sizeof(NSVGgradientStop)); + grad->nstops = nstops; + + *paintType = data->type; + + return grad; +} + +static float nsvg__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 void nsvg__getLocalBounds(float* bounds, NSVGshape* shape, float* xform) { + NSVGpath* path; + float curve[4 * 2], curveBounds[4]; + int i, first = 1; + for (path = shape->paths; path != NULL; path = path->next) { + nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform); + for (i = 0; i < path->npts - 1; i += 3) { + nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i + 1) * 2], path->pts[(i + 1) * 2 + 1], xform); + nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i + 2) * 2], path->pts[(i + 2) * 2 + 1], xform); + nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i + 3) * 2], path->pts[(i + 3) * 2 + 1], xform); + nsvg__curveBounds(curveBounds, curve); + if (first) { + bounds[0] = curveBounds[0]; + bounds[1] = curveBounds[1]; + bounds[2] = curveBounds[2]; + bounds[3] = curveBounds[3]; + first = 0; + } else { + bounds[0] = nsvg__minf(bounds[0], curveBounds[0]); + bounds[1] = nsvg__minf(bounds[1], curveBounds[1]); + bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]); + bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]); + } + curve[0] = curve[6]; + curve[1] = curve[7]; + } + } +} + +static void nsvg__addShape(NSVGparser* p) { + NSVGattrib* attr = nsvg__getAttr(p); + float scale = 1.0f; + NSVGshape* shape; + NSVGpath* path; + int i; + + if (p->plist == NULL) + return; + + shape = (NSVGshape*)malloc(sizeof(NSVGshape)); + if (shape == NULL) + goto error; + memset(shape, 0, sizeof(NSVGshape)); + + memcpy(shape->id, attr->id, sizeof shape->id); + memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient); + memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient); + memcpy(shape->xform, attr->xform, sizeof shape->xform); + scale = nsvg__getAverageScale(attr->xform); + shape->strokeWidth = attr->strokeWidth * scale; + shape->strokeDashOffset = attr->strokeDashOffset * scale; + shape->strokeDashCount = (char)attr->strokeDashCount; + for (i = 0; i < attr->strokeDashCount; i++) + shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; + shape->strokeLineJoin = attr->strokeLineJoin; + shape->strokeLineCap = attr->strokeLineCap; + shape->miterLimit = attr->miterLimit; + shape->fillRule = attr->fillRule; + shape->opacity = attr->opacity; + shape->paintOrder = attr->paintOrder; + + shape->paths = p->plist; + p->plist = NULL; + + // Calculate shape bounds + shape->bounds[0] = shape->paths->bounds[0]; + shape->bounds[1] = shape->paths->bounds[1]; + shape->bounds[2] = shape->paths->bounds[2]; + shape->bounds[3] = shape->paths->bounds[3]; + for (path = shape->paths->next; path != NULL; path = path->next) { + shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]); + shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); + shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); + shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); + } + + // Set fill + if (attr->hasFill == 0) { + shape->fill.type = NSVG_PAINT_NONE; + } else if (attr->hasFill == 1) { + shape->fill.type = NSVG_PAINT_COLOR; + shape->fill.color = attr->fillColor; + shape->fill.color |= (unsigned int)(attr->fillOpacity * 255) << 24; + } else if (attr->hasFill == 2) { + shape->fill.type = NSVG_PAINT_UNDEF; + } + + // Set stroke + if (attr->hasStroke == 0) { + shape->stroke.type = NSVG_PAINT_NONE; + } else if (attr->hasStroke == 1) { + shape->stroke.type = NSVG_PAINT_COLOR; + shape->stroke.color = attr->strokeColor; + shape->stroke.color |= (unsigned int)(attr->strokeOpacity * 255) << 24; + } else if (attr->hasStroke == 2) { + shape->stroke.type = NSVG_PAINT_UNDEF; + } + + // Set flags + shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00); + + // Add to tail + if (p->image->shapes == NULL) + p->image->shapes = shape; + else + p->shapesTail->next = shape; + p->shapesTail = shape; + + return; + +error: + if (shape) + free(shape); +} + +static void nsvg__addPath(NSVGparser* p, char closed) { + NSVGattrib* attr = nsvg__getAttr(p); + NSVGpath* path = NULL; + float bounds[4]; + float* curve; + int i; + + if (p->npts < 4) + return; + + if (closed) + nsvg__lineTo(p, p->pts[0], p->pts[1]); + + // Expect 1 + N*3 points (N = number of cubic bezier segments). + if ((p->npts % 3) != 1) + return; + + path = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (path == NULL) + goto error; + memset(path, 0, sizeof(NSVGpath)); + + path->pts = (float*)malloc(p->npts * 2 * sizeof(float)); + if (path->pts == NULL) + goto error; + path->closed = closed; + path->npts = p->npts; + + // Transform path. + for (i = 0; i < p->npts; ++i) + nsvg__xformPoint(&path->pts[i * 2], &path->pts[i * 2 + 1], p->pts[i * 2], p->pts[i * 2 + 1], attr->xform); + + // Find bounds + for (i = 0; i < path->npts - 1; i += 3) { + curve = &path->pts[i * 2]; + nsvg__curveBounds(bounds, curve); + if (i == 0) { + path->bounds[0] = bounds[0]; + path->bounds[1] = bounds[1]; + path->bounds[2] = bounds[2]; + path->bounds[3] = bounds[3]; + } else { + path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]); + path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]); + path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]); + path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]); + } + } + + path->next = p->plist; + p->plist = path; + + return; + +error: + if (path != NULL) { + if (path->pts != NULL) + free(path->pts); + free(path); + } +} + +// We roll our own string to float because the std library one uses locale and messes things up. +static double nsvg__atof(const char* s) { + char* cur = (char*)s; + char* end = NULL; + double res = 0.0, sign = 1.0; + long long intPart = 0, fracPart = 0; + char hasIntPart = 0, hasFracPart = 0; + + // Parse optional sign + if (*cur == '+') { + cur++; + } else if (*cur == '-') { + sign = -1; + cur++; + } + + // Parse integer part + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + intPart = strtoll(cur, &end, 10); + if (cur != end) { + res = (double)intPart; + hasIntPart = 1; + cur = end; + } + } + + // Parse fractional part. + if (*cur == '.') { + cur++; // Skip '.' + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + fracPart = strtoll(cur, &end, 10); + if (cur != end) { + res += (double)fracPart / pow(10.0, (double)(end - cur)); + hasFracPart = 1; + cur = end; + } + } + } + + // A valid number should have integer or fractional part. + if (!hasIntPart && !hasFracPart) + return 0.0; + + // Parse optional exponent + if (*cur == 'e' || *cur == 'E') { + long expPart = 0; + cur++; // skip 'E' + expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + if (cur != end) { + res *= pow(10.0, (double)expPart); + } + } + + return res * sign; +} + +static const char* nsvg__parseNumber(const char* s, char* it, const int size) { + const int last = size - 1; + int i = 0; + + // sign + if (*s == '-' || *s == '+') { + if (i < last) + it[i++] = *s; + s++; + } + // integer part + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + if (*s == '.') { + // decimal point + if (i < last) + it[i++] = *s; + s++; + // fraction part + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + } + // exponent + if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) { + if (i < last) + it[i++] = *s; + s++; + if (*s == '-' || *s == '+') { + if (i < last) + it[i++] = *s; + s++; + } + while (*s && nsvg__isdigit(*s)) { + if (i < last) + it[i++] = *s; + s++; + } + } + it[i] = '\0'; + + return s; +} + +static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it) { + it[0] = '\0'; + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + if (!*s) + return s; + if (*s == '0' || *s == '1') { + it[0] = *s++; + it[1] = '\0'; + return s; + } + return s; +} + +static const char* nsvg__getNextPathItem(const char* s, char* it) { + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + if (!*s) + return s; + if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { + s = nsvg__parseNumber(s, it, 64); + } else { + // Parse command + it[0] = *s++; + it[1] = '\0'; + return s; + } + + return s; +} + +static unsigned int nsvg__parseColorHex(const char* str) { + unsigned int r = 0, g = 0, b = 0; + if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3) // 2 digit hex + return NSVG_RGB(r, g, b); + if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3) // 1 digit hex, e.g. #abc -> 0xccbbaa + return NSVG_RGB(r * 17, g * 17, b * 17); // same effect as (r<<4|r), (g<<4|g), .. + return NSVG_RGB(128, 128, 128); +} + +// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters). +// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors +// for backwards compatibility. Note: other image viewers return black instead. + +static unsigned int nsvg__parseColorRGB(const char* str) { + int i; + unsigned int rgbi[3]; + float rgbf[3]; + // try decimal integers first + if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) { + // integers failed, try percent values (float, locale independent) + const char delimiter[3] = {',', ',', ')'}; + str += 4; // skip "rgb(" + for (i = 0; i < 3; i++) { + while (*str && (nsvg__isspace(*str))) + str++; // skip leading spaces + if (*str == '+') + str++; // skip '+' (don't allow '-') + if (!*str) + break; + rgbf[i] = nsvg__atof(str); + + // Note 1: it would be great if nsvg__atof() returned how many + // bytes it consumed but it doesn't. We need to skip the number, + // the '%' character, spaces, and the delimiter ',' or ')'. + + // Note 2: The following code does not allow values like "33.%", + // i.e. a decimal point w/o fractional part, but this is consistent + // with other image viewers, e.g. firefox, chrome, eog, gimp. + + while (*str && nsvg__isdigit(*str)) + str++; // skip integer part + if (*str == '.') { + str++; + if (!nsvg__isdigit(*str)) + break; // error: no digit after '.' + while (*str && nsvg__isdigit(*str)) + str++; // skip fractional part + } + if (*str == '%') + str++; + else + break; + while (*str && nsvg__isspace(*str)) + str++; + if (*str == delimiter[i]) + str++; + else + break; + } + if (i == 3) { + rgbi[0] = roundf(rgbf[0] * 2.55f); + rgbi[1] = roundf(rgbf[1] * 2.55f); + rgbi[2] = roundf(rgbf[2] * 2.55f); + } else { + rgbi[0] = rgbi[1] = rgbi[2] = 128; + } + } + // clip values as the CSS spec requires + for (i = 0; i < 3; i++) { + if (rgbi[i] > 255) + rgbi[i] = 255; + } + return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]); +} + +typedef struct NSVGNamedColor { + const char* name; + unsigned int color; +} NSVGNamedColor; + +NSVGNamedColor nsvg__colors[] = { + + {"red", NSVG_RGB(255, 0, 0)}, + {"green", NSVG_RGB(0, 128, 0)}, + {"blue", NSVG_RGB(0, 0, 255)}, + {"yellow", NSVG_RGB(255, 255, 0)}, + {"cyan", NSVG_RGB(0, 255, 255)}, + {"magenta", NSVG_RGB(255, 0, 255)}, + {"black", NSVG_RGB(0, 0, 0)}, + {"grey", NSVG_RGB(128, 128, 128)}, + {"gray", NSVG_RGB(128, 128, 128)}, + {"white", NSVG_RGB(255, 255, 255)}, + +#ifdef NANOSVG_ALL_COLOR_KEYWORDS + {"aliceblue", NSVG_RGB(240, 248, 255)}, + {"antiquewhite", NSVG_RGB(250, 235, 215)}, + {"aqua", NSVG_RGB(0, 255, 255)}, + {"aquamarine", NSVG_RGB(127, 255, 212)}, + {"azure", NSVG_RGB(240, 255, 255)}, + {"beige", NSVG_RGB(245, 245, 220)}, + {"bisque", NSVG_RGB(255, 228, 196)}, + {"blanchedalmond", NSVG_RGB(255, 235, 205)}, + {"blueviolet", NSVG_RGB(138, 43, 226)}, + {"brown", NSVG_RGB(165, 42, 42)}, + {"burlywood", NSVG_RGB(222, 184, 135)}, + {"cadetblue", NSVG_RGB(95, 158, 160)}, + {"chartreuse", NSVG_RGB(127, 255, 0)}, + {"chocolate", NSVG_RGB(210, 105, 30)}, + {"coral", NSVG_RGB(255, 127, 80)}, + {"cornflowerblue", NSVG_RGB(100, 149, 237)}, + {"cornsilk", NSVG_RGB(255, 248, 220)}, + {"crimson", NSVG_RGB(220, 20, 60)}, + {"darkblue", NSVG_RGB(0, 0, 139)}, + {"darkcyan", NSVG_RGB(0, 139, 139)}, + {"darkgoldenrod", NSVG_RGB(184, 134, 11)}, + {"darkgray", NSVG_RGB(169, 169, 169)}, + {"darkgreen", NSVG_RGB(0, 100, 0)}, + {"darkgrey", NSVG_RGB(169, 169, 169)}, + {"darkkhaki", NSVG_RGB(189, 183, 107)}, + {"darkmagenta", NSVG_RGB(139, 0, 139)}, + {"darkolivegreen", NSVG_RGB(85, 107, 47)}, + {"darkorange", NSVG_RGB(255, 140, 0)}, + {"darkorchid", NSVG_RGB(153, 50, 204)}, + {"darkred", NSVG_RGB(139, 0, 0)}, + {"darksalmon", NSVG_RGB(233, 150, 122)}, + {"darkseagreen", NSVG_RGB(143, 188, 143)}, + {"darkslateblue", NSVG_RGB(72, 61, 139)}, + {"darkslategray", NSVG_RGB(47, 79, 79)}, + {"darkslategrey", NSVG_RGB(47, 79, 79)}, + {"darkturquoise", NSVG_RGB(0, 206, 209)}, + {"darkviolet", NSVG_RGB(148, 0, 211)}, + {"deeppink", NSVG_RGB(255, 20, 147)}, + {"deepskyblue", NSVG_RGB(0, 191, 255)}, + {"dimgray", NSVG_RGB(105, 105, 105)}, + {"dimgrey", NSVG_RGB(105, 105, 105)}, + {"dodgerblue", NSVG_RGB(30, 144, 255)}, + {"firebrick", NSVG_RGB(178, 34, 34)}, + {"floralwhite", NSVG_RGB(255, 250, 240)}, + {"forestgreen", NSVG_RGB(34, 139, 34)}, + {"fuchsia", NSVG_RGB(255, 0, 255)}, + {"gainsboro", NSVG_RGB(220, 220, 220)}, + {"ghostwhite", NSVG_RGB(248, 248, 255)}, + {"gold", NSVG_RGB(255, 215, 0)}, + {"goldenrod", NSVG_RGB(218, 165, 32)}, + {"greenyellow", NSVG_RGB(173, 255, 47)}, + {"honeydew", NSVG_RGB(240, 255, 240)}, + {"hotpink", NSVG_RGB(255, 105, 180)}, + {"indianred", NSVG_RGB(205, 92, 92)}, + {"indigo", NSVG_RGB(75, 0, 130)}, + {"ivory", NSVG_RGB(255, 255, 240)}, + {"khaki", NSVG_RGB(240, 230, 140)}, + {"lavender", NSVG_RGB(230, 230, 250)}, + {"lavenderblush", NSVG_RGB(255, 240, 245)}, + {"lawngreen", NSVG_RGB(124, 252, 0)}, + {"lemonchiffon", NSVG_RGB(255, 250, 205)}, + {"lightblue", NSVG_RGB(173, 216, 230)}, + {"lightcoral", NSVG_RGB(240, 128, 128)}, + {"lightcyan", NSVG_RGB(224, 255, 255)}, + {"lightgoldenrodyellow", NSVG_RGB(250, 250, 210)}, + {"lightgray", NSVG_RGB(211, 211, 211)}, + {"lightgreen", NSVG_RGB(144, 238, 144)}, + {"lightgrey", NSVG_RGB(211, 211, 211)}, + {"lightpink", NSVG_RGB(255, 182, 193)}, + {"lightsalmon", NSVG_RGB(255, 160, 122)}, + {"lightseagreen", NSVG_RGB(32, 178, 170)}, + {"lightskyblue", NSVG_RGB(135, 206, 250)}, + {"lightslategray", NSVG_RGB(119, 136, 153)}, + {"lightslategrey", NSVG_RGB(119, 136, 153)}, + {"lightsteelblue", NSVG_RGB(176, 196, 222)}, + {"lightyellow", NSVG_RGB(255, 255, 224)}, + {"lime", NSVG_RGB(0, 255, 0)}, + {"limegreen", NSVG_RGB(50, 205, 50)}, + {"linen", NSVG_RGB(250, 240, 230)}, + {"maroon", NSVG_RGB(128, 0, 0)}, + {"mediumaquamarine", NSVG_RGB(102, 205, 170)}, + {"mediumblue", NSVG_RGB(0, 0, 205)}, + {"mediumorchid", NSVG_RGB(186, 85, 211)}, + {"mediumpurple", NSVG_RGB(147, 112, 219)}, + {"mediumseagreen", NSVG_RGB(60, 179, 113)}, + {"mediumslateblue", NSVG_RGB(123, 104, 238)}, + {"mediumspringgreen", NSVG_RGB(0, 250, 154)}, + {"mediumturquoise", NSVG_RGB(72, 209, 204)}, + {"mediumvioletred", NSVG_RGB(199, 21, 133)}, + {"midnightblue", NSVG_RGB(25, 25, 112)}, + {"mintcream", NSVG_RGB(245, 255, 250)}, + {"mistyrose", NSVG_RGB(255, 228, 225)}, + {"moccasin", NSVG_RGB(255, 228, 181)}, + {"navajowhite", NSVG_RGB(255, 222, 173)}, + {"navy", NSVG_RGB(0, 0, 128)}, + {"oldlace", NSVG_RGB(253, 245, 230)}, + {"olive", NSVG_RGB(128, 128, 0)}, + {"olivedrab", NSVG_RGB(107, 142, 35)}, + {"orange", NSVG_RGB(255, 165, 0)}, + {"orangered", NSVG_RGB(255, 69, 0)}, + {"orchid", NSVG_RGB(218, 112, 214)}, + {"palegoldenrod", NSVG_RGB(238, 232, 170)}, + {"palegreen", NSVG_RGB(152, 251, 152)}, + {"paleturquoise", NSVG_RGB(175, 238, 238)}, + {"palevioletred", NSVG_RGB(219, 112, 147)}, + {"papayawhip", NSVG_RGB(255, 239, 213)}, + {"peachpuff", NSVG_RGB(255, 218, 185)}, + {"peru", NSVG_RGB(205, 133, 63)}, + {"pink", NSVG_RGB(255, 192, 203)}, + {"plum", NSVG_RGB(221, 160, 221)}, + {"powderblue", NSVG_RGB(176, 224, 230)}, + {"purple", NSVG_RGB(128, 0, 128)}, + {"rosybrown", NSVG_RGB(188, 143, 143)}, + {"royalblue", NSVG_RGB(65, 105, 225)}, + {"saddlebrown", NSVG_RGB(139, 69, 19)}, + {"salmon", NSVG_RGB(250, 128, 114)}, + {"sandybrown", NSVG_RGB(244, 164, 96)}, + {"seagreen", NSVG_RGB(46, 139, 87)}, + {"seashell", NSVG_RGB(255, 245, 238)}, + {"sienna", NSVG_RGB(160, 82, 45)}, + {"silver", NSVG_RGB(192, 192, 192)}, + {"skyblue", NSVG_RGB(135, 206, 235)}, + {"slateblue", NSVG_RGB(106, 90, 205)}, + {"slategray", NSVG_RGB(112, 128, 144)}, + {"slategrey", NSVG_RGB(112, 128, 144)}, + {"snow", NSVG_RGB(255, 250, 250)}, + {"springgreen", NSVG_RGB(0, 255, 127)}, + {"steelblue", NSVG_RGB(70, 130, 180)}, + {"tan", NSVG_RGB(210, 180, 140)}, + {"teal", NSVG_RGB(0, 128, 128)}, + {"thistle", NSVG_RGB(216, 191, 216)}, + {"tomato", NSVG_RGB(255, 99, 71)}, + {"turquoise", NSVG_RGB(64, 224, 208)}, + {"violet", NSVG_RGB(238, 130, 238)}, + {"wheat", NSVG_RGB(245, 222, 179)}, + {"whitesmoke", NSVG_RGB(245, 245, 245)}, + {"yellowgreen", NSVG_RGB(154, 205, 50)}, +#endif +}; + +static unsigned int nsvg__parseColorName(const char* str) { + int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor); + + for (i = 0; i < ncolors; i++) { + if (strcmp(nsvg__colors[i].name, str) == 0) { + return nsvg__colors[i].color; + } + } + + return NSVG_RGB(128, 128, 128); +} + +static unsigned int nsvg__parseColor(const char* str) { + size_t len = 0; + while (*str == ' ') + ++str; + len = strlen(str); + if (len >= 1 && *str == '#') + return nsvg__parseColorHex(str); + else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(') + return nsvg__parseColorRGB(str); + return nsvg__parseColorName(str); +} + +static float nsvg__parseOpacity(const char* str) { + float val = nsvg__atof(str); + if (val < 0.0f) + val = 0.0f; + if (val > 1.0f) + val = 1.0f; + return val; +} + +static float nsvg__parseMiterLimit(const char* str) { + float val = nsvg__atof(str); + if (val < 0.0f) + val = 0.0f; + return val; +} + +static int nsvg__parseUnits(const char* units) { + if (units[0] == 'p' && units[1] == 'x') + return NSVG_UNITS_PX; + else if (units[0] == 'p' && units[1] == 't') + return NSVG_UNITS_PT; + else if (units[0] == 'p' && units[1] == 'c') + return NSVG_UNITS_PC; + else if (units[0] == 'm' && units[1] == 'm') + return NSVG_UNITS_MM; + else if (units[0] == 'c' && units[1] == 'm') + return NSVG_UNITS_CM; + else if (units[0] == 'i' && units[1] == 'n') + return NSVG_UNITS_IN; + else if (units[0] == '%') + return NSVG_UNITS_PERCENT; + else if (units[0] == 'e' && units[1] == 'm') + return NSVG_UNITS_EM; + else if (units[0] == 'e' && units[1] == 'x') + return NSVG_UNITS_EX; + return NSVG_UNITS_USER; +} + +static int nsvg__isCoordinate(const char* s) { + // optional sign + if (*s == '-' || *s == '+') + s++; + // must have at least one digit, or start by a dot + return (nsvg__isdigit(*s) || *s == '.'); +} + +static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) { + NSVGcoordinate coord = {0, NSVG_UNITS_USER}; + char buf[64]; + coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64)); + coord.value = nsvg__atof(buf); + return coord; +} + +static NSVGcoordinate nsvg__coord(float v, int units) { + NSVGcoordinate coord = {v, units}; + return coord; +} + +static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length) { + NSVGcoordinate coord = nsvg__parseCoordinateRaw(str); + return nsvg__convertToPixels(p, coord, orig, length); +} + +static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na) { + const char* end; + const char* ptr; + char it[64]; + + *na = 0; + ptr = str; + while (*ptr && *ptr != '(') + ++ptr; + if (*ptr == 0) + return 1; + end = ptr; + while (*end && *end != ')') + ++end; + if (*end == 0) + return 1; + + while (ptr < end) { + if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { + if (*na >= maxNa) + return 0; + ptr = nsvg__parseNumber(ptr, it, 64); + args[(*na)++] = (float)nsvg__atof(it); + } else { + ++ptr; + } + } + return (int)(end - str); +} + +static int nsvg__parseMatrix(float* xform, const char* str) { + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, t, 6, &na); + if (na != 6) + return len; + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseTranslate(float* xform, const char* str) { + float args[2]; + float t[6]; + int na = 0; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) + args[1] = 0.0; + + nsvg__xformSetTranslation(t, args[0], args[1]); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseScale(float* xform, const char* str) { + float args[2]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 2, &na); + if (na == 1) + args[1] = args[0]; + nsvg__xformSetScale(t, args[0], args[1]); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseSkewX(float* xform, const char* str) { + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewX(t, args[0] / 180.0f * NSVG_PI); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseSkewY(float* xform, const char* str) { + float args[1]; + int na = 0; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 1, &na); + nsvg__xformSetSkewY(t, args[0] / 180.0f * NSVG_PI); + memcpy(xform, t, sizeof(float) * 6); + return len; +} + +static int nsvg__parseRotate(float* xform, const char* str) { + float args[3]; + int na = 0; + float m[6]; + float t[6]; + int len = nsvg__parseTransformArgs(str, args, 3, &na); + if (na == 1) + args[1] = args[2] = 0.0f; + nsvg__xformIdentity(m); + + if (na > 1) { + nsvg__xformSetTranslation(t, -args[1], -args[2]); + nsvg__xformMultiply(m, t); + } + + nsvg__xformSetRotation(t, args[0] / 180.0f * NSVG_PI); + nsvg__xformMultiply(m, t); + + if (na > 1) { + nsvg__xformSetTranslation(t, args[1], args[2]); + nsvg__xformMultiply(m, t); + } + + memcpy(xform, m, sizeof(float) * 6); + + return len; +} + +static void nsvg__parseTransform(float* xform, const char* str) { + float t[6]; + int len; + nsvg__xformIdentity(xform); + while (*str) { + if (strncmp(str, "matrix", 6) == 0) + len = nsvg__parseMatrix(t, str); + else if (strncmp(str, "translate", 9) == 0) + len = nsvg__parseTranslate(t, str); + else if (strncmp(str, "scale", 5) == 0) + len = nsvg__parseScale(t, str); + else if (strncmp(str, "rotate", 6) == 0) + len = nsvg__parseRotate(t, str); + else if (strncmp(str, "skewX", 5) == 0) + len = nsvg__parseSkewX(t, str); + else if (strncmp(str, "skewY", 5) == 0) + len = nsvg__parseSkewY(t, str); + else { + ++str; + continue; + } + if (len != 0) { + str += len; + } else { + ++str; + continue; + } + + nsvg__xformPremultiply(xform, t); + } +} + +static void nsvg__parseUrl(char* id, const char* str) { + int i = 0; + str += 4; // "url("; + if (*str && *str == '#') + str++; + while (i < 63 && *str && *str != ')') { + id[i] = *str++; + i++; + } + id[i] = '\0'; +} + +static char nsvg__parseLineCap(const char* str) { + if (strcmp(str, "butt") == 0) + return NSVG_CAP_BUTT; + else if (strcmp(str, "round") == 0) + return NSVG_CAP_ROUND; + else if (strcmp(str, "square") == 0) + return NSVG_CAP_SQUARE; + // TODO: handle inherit. + return NSVG_CAP_BUTT; +} + +static char nsvg__parseLineJoin(const char* str) { + if (strcmp(str, "miter") == 0) + return NSVG_JOIN_MITER; + else if (strcmp(str, "round") == 0) + return NSVG_JOIN_ROUND; + else if (strcmp(str, "bevel") == 0) + return NSVG_JOIN_BEVEL; + // TODO: handle inherit. + return NSVG_JOIN_MITER; +} + +static char nsvg__parseFillRule(const char* str) { + if (strcmp(str, "nonzero") == 0) + return NSVG_FILLRULE_NONZERO; + else if (strcmp(str, "evenodd") == 0) + return NSVG_FILLRULE_EVENODD; + // TODO: handle inherit. + return NSVG_FILLRULE_NONZERO; +} + +static unsigned char nsvg__parsePaintOrder(const char* str) { + if (strcmp(str, "normal") == 0 || strcmp(str, "fill stroke markers") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); + else if (strcmp(str, "fill markers stroke") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE); + else if (strcmp(str, "markers fill stroke") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_FILL, NSVG_PAINT_STROKE); + else if (strcmp(str, "markers stroke fill") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_MARKERS, NSVG_PAINT_STROKE, NSVG_PAINT_FILL); + else if (strcmp(str, "stroke fill markers") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_FILL, NSVG_PAINT_MARKERS); + else if (strcmp(str, "stroke markers fill") == 0) + return nsvg__encodePaintOrder(NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS, NSVG_PAINT_FILL); + // TODO: handle inherit. + return nsvg__encodePaintOrder(NSVG_PAINT_FILL, NSVG_PAINT_STROKE, NSVG_PAINT_MARKERS); +} + +static const char* nsvg__getNextDashItem(const char* s, char* it) { + int n = 0; + it[0] = '\0'; + // Skip white spaces and commas + while (*s && (nsvg__isspace(*s) || *s == ',')) + s++; + // Advance until whitespace, comma or end. + while (*s && (!nsvg__isspace(*s) && *s != ',')) { + if (n < 63) + it[n++] = *s; + s++; + } + it[n++] = '\0'; + return s; +} + +static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray) { + char item[64]; + int count = 0, i; + float sum = 0.0f; + + // Handle "none" + if (str[0] == 'n') + return 0; + + // Parse dashes + while (*str) { + str = nsvg__getNextDashItem(str, item); + if (!*item) + break; + if (count < NSVG_MAX_DASHES) + strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); + } + + for (i = 0; i < count; i++) + sum += strokeDashArray[i]; + if (sum <= 1e-6f) + count = 0; + + return count; +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str); + +static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) { + float xform[6]; + NSVGattrib* attr = nsvg__getAttr(p); + if (!attr) + return 0; + + if (strcmp(name, "style") == 0) { + nsvg__parseStyle(p, value); + } else if (strcmp(name, "display") == 0) { + if (strcmp(value, "none") == 0) + attr->visible = 0; + // Don't reset ->visible on display:inline, one display:none hides the whole subtree + + } else if (strcmp(name, "fill") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasFill = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasFill = 2; + nsvg__parseUrl(attr->fillGradient, value); + } else { + attr->hasFill = 1; + attr->fillColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "opacity") == 0) { + attr->opacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "fill-opacity") == 0) { + attr->fillOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke") == 0) { + if (strcmp(value, "none") == 0) { + attr->hasStroke = 0; + } else if (strncmp(value, "url(", 4) == 0) { + attr->hasStroke = 2; + nsvg__parseUrl(attr->strokeGradient, value); + } else { + attr->hasStroke = 1; + attr->strokeColor = nsvg__parseColor(value); + } + } else if (strcmp(name, "stroke-width") == 0) { + attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-dasharray") == 0) { + attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray); + } else if (strcmp(name, "stroke-dashoffset") == 0) { + attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "stroke-opacity") == 0) { + attr->strokeOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "stroke-linecap") == 0) { + attr->strokeLineCap = nsvg__parseLineCap(value); + } else if (strcmp(name, "stroke-linejoin") == 0) { + attr->strokeLineJoin = nsvg__parseLineJoin(value); + } else if (strcmp(name, "stroke-miterlimit") == 0) { + attr->miterLimit = nsvg__parseMiterLimit(value); + } else if (strcmp(name, "fill-rule") == 0) { + attr->fillRule = nsvg__parseFillRule(value); + } else if (strcmp(name, "font-size") == 0) { + attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p)); + } else if (strcmp(name, "transform") == 0) { + nsvg__parseTransform(xform, value); + nsvg__xformPremultiply(attr->xform, xform); + } else if (strcmp(name, "stop-color") == 0) { + attr->stopColor = nsvg__parseColor(value); + } else if (strcmp(name, "stop-opacity") == 0) { + attr->stopOpacity = nsvg__parseOpacity(value); + } else if (strcmp(name, "offset") == 0) { + attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f); + } else if (strcmp(name, "paint-order") == 0) { + attr->paintOrder = nsvg__parsePaintOrder(value); + } else if (strcmp(name, "id") == 0) { + strncpy(attr->id, value, 63); + attr->id[63] = '\0'; + } else { + return 0; + } + return 1; +} + +static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end) { + const char* str; + const char* val; + char name[512]; + char value[512]; + int n; + + str = start; + while (str < end && *str != ':') + ++str; + + val = str; + + // Right Trim + while (str > start && (*str == ':' || nsvg__isspace(*str))) + --str; + ++str; + + n = (int)(str - start); + if (n > 511) + n = 511; + if (n) + memcpy(name, start, n); + name[n] = 0; + + while (val < end && (*val == ':' || nsvg__isspace(*val))) + ++val; + + n = (int)(end - val); + if (n > 511) + n = 511; + if (n) + memcpy(value, val, n); + value[n] = 0; + + return nsvg__parseAttr(p, name, value); +} + +static void nsvg__parseStyle(NSVGparser* p, const char* str) { + const char* start; + const char* end; + + while (*str) { + // Left Trim + while (*str && nsvg__isspace(*str)) + ++str; + start = str; + while (*str && *str != ';') + ++str; + end = str; + + // Right Trim + while (end > start && (*end == ';' || nsvg__isspace(*end))) + --end; + ++end; + + nsvg__parseNameValue(p, start, end); + if (*str) + ++str; + } +} + +static void nsvg__parseAttribs(NSVGparser* p, const char** attr) { + int i; + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "style") == 0) + nsvg__parseStyle(p, attr[i + 1]); + else + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } +} + +static int nsvg__getArgsPerElement(char cmd) { + switch (cmd) { + case 'v': + case 'V': + case 'h': + case 'H': + return 1; + case 'm': + case 'M': + case 'l': + case 'L': + case 't': + case 'T': + return 2; + case 'q': + case 'Q': + case 's': + case 'S': + return 4; + case 'c': + case 'C': + return 6; + case 'a': + case 'A': + return 7; + case 'z': + case 'Z': + return 0; + } + return -1; +} + +static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__moveTo(p, *cpx, *cpy); +} + +static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) { + *cpx += args[0]; + *cpy += args[1]; + } else { + *cpx = args[0]; + *cpy = args[1]; + } + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) + *cpx += args[0]; + else + *cpx = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + if (rel) + *cpy += args[0]; + else + *cpy = args[0]; + nsvg__lineTo(p, *cpx, *cpy); +} + +static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x2, y2, cx1, cy1, cx2, cy2; + + if (rel) { + cx1 = *cpx + args[0]; + cy1 = *cpy + args[1]; + cx2 = *cpx + args[2]; + cy2 = *cpy + args[3]; + x2 = *cpx + args[4]; + y2 = *cpy + args[5]; + } else { + cx1 = args[0]; + cy1 = args[1]; + cx2 = args[2]; + cy2 = args[3]; + x2 = args[4]; + y2 = args[5]; + } + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx2 = *cpx + args[0]; + cy2 = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx2 = args[0]; + cy2 = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + cx1 = 2 * x1 - *cpx2; + cy1 = 2 * y1 - *cpy2; + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx2; + *cpy2 = cy2; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + cx = *cpx + args[0]; + cy = *cpy + args[1]; + x2 = *cpx + args[2]; + y2 = *cpy + args[3]; + } else { + cx = args[0]; + cy = args[1]; + x2 = args[2]; + y2 = args[3]; + } + + // Convert to cubic bezier + cx1 = x1 + 2.0f / 3.0f * (cx - x1); + cy1 = y1 + 2.0f / 3.0f * (cy - y1); + cx2 = x2 + 2.0f / 3.0f * (cx - x2); + cy2 = y2 + 2.0f / 3.0f * (cy - y2); + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy, float* cpx2, float* cpy2, float* args, int rel) { + float x1, y1, x2, y2, cx, cy; + float cx1, cy1, cx2, cy2; + + x1 = *cpx; + y1 = *cpy; + if (rel) { + x2 = *cpx + args[0]; + y2 = *cpy + args[1]; + } else { + x2 = args[0]; + y2 = args[1]; + } + + cx = 2 * x1 - *cpx2; + cy = 2 * y1 - *cpy2; + + // Convert to cubix bezier + cx1 = x1 + 2.0f / 3.0f * (cx - x1); + cy1 = y1 + 2.0f / 3.0f * (cy - y1); + cx2 = x2 + 2.0f / 3.0f * (cx - x2); + cy2 = y2 + 2.0f / 3.0f * (cy - y2); + + nsvg__cubicBezTo(p, cx1, cy1, cx2, cy2, x2, y2); + + *cpx2 = cx; + *cpy2 = cy; + *cpx = x2; + *cpy = y2; +} + +static float nsvg__sqr(float x) { return x * x; } +static float nsvg__vmag(float x, float y) { return sqrtf(x * x + y * y); } + +static float nsvg__vecrat(float ux, float uy, float vx, float vy) { return (ux * vx + uy * vy) / (nsvg__vmag(ux, uy) * nsvg__vmag(vx, vy)); } + +static float nsvg__vecang(float ux, float uy, float vx, float vy) { + float r = nsvg__vecrat(ux, uy, vx, vy); + if (r < -1.0f) + r = -1.0f; + if (r > 1.0f) + r = 1.0f; + return ((ux * vy < uy * vx) ? -1.0f : 1.0f) * acosf(r); +} + +static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { + // Ported from canvg (https://code.google.com/p/canvg/) + float rx, ry, rotx; + float x1, y1, x2, y2, cx, cy, dx, dy, d; + float x1p, y1p, cxp, cyp, s, sa, sb; + float ux, uy, vx, vy, a1, da; + float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; + float sinrx, cosrx; + int fa, fs; + int i, ndivs; + float hda, kappa; + + rx = fabsf(args[0]); // y radius + ry = fabsf(args[1]); // x radius + rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle + fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc + fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction + x1 = *cpx; // start point + y1 = *cpy; + if (rel) { // end point + x2 = *cpx + args[5]; + y2 = *cpy + args[6]; + } else { + x2 = args[5]; + y2 = args[6]; + } + + dx = x1 - x2; + dy = y1 - y2; + d = sqrtf(dx * dx + dy * dy); + if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { + // The arc degenerates to a line + nsvg__lineTo(p, x2, y2); + *cpx = x2; + *cpy = y2; + return; + } + + sinrx = sinf(rotx); + cosrx = cosf(rotx); + + // Convert to center point parameterization. + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // 1) Compute x1', y1' + x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; + y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; + d = nsvg__sqr(x1p) / nsvg__sqr(rx) + nsvg__sqr(y1p) / nsvg__sqr(ry); + if (d > 1) { + d = sqrtf(d); + rx *= d; + ry *= d; + } + // 2) Compute cx', cy' + s = 0.0f; + sa = nsvg__sqr(rx) * nsvg__sqr(ry) - nsvg__sqr(rx) * nsvg__sqr(y1p) - nsvg__sqr(ry) * nsvg__sqr(x1p); + sb = nsvg__sqr(rx) * nsvg__sqr(y1p) + nsvg__sqr(ry) * nsvg__sqr(x1p); + if (sa < 0.0f) + sa = 0.0f; + if (sb > 0.0f) + s = sqrtf(sa / sb); + if (fa == fs) + s = -s; + cxp = s * rx * y1p / ry; + cyp = s * -ry * x1p / rx; + + // 3) Compute cx,cy from cx',cy' + cx = (x1 + x2) / 2.0f + cosrx * cxp - sinrx * cyp; + cy = (y1 + y2) / 2.0f + sinrx * cxp + cosrx * cyp; + + // 4) Calculate theta1, and delta theta. + ux = (x1p - cxp) / rx; + uy = (y1p - cyp) / ry; + vx = (-x1p - cxp) / rx; + vy = (-y1p - cyp) / ry; + a1 = nsvg__vecang(1.0f, 0.0f, ux, uy); // Initial angle + da = nsvg__vecang(ux, uy, vx, vy); // Delta angle + + // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; + // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; + + if (fs == 0 && da > 0) + da -= 2 * NSVG_PI; + else if (fs == 1 && da < 0) + da += 2 * NSVG_PI; + + // Approximate the arc using cubic spline segments. + t[0] = cosrx; + t[1] = sinrx; + t[2] = -sinrx; + t[3] = cosrx; + t[4] = cx; + t[5] = cy; + + // Split arc into max 90 degree segments. + // The loop assumes an iteration per end point (including start and end), this +1. + ndivs = (int)(fabsf(da) / (NSVG_PI * 0.5f) + 1.0f); + hda = (da / (float)ndivs) / 2.0f; + // Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) + if ((hda < 1e-3f) && (hda > -1e-3f)) + hda *= 0.5f; + else + hda = (1.0f - cosf(hda)) / sinf(hda); + kappa = fabsf(4.0f / 3.0f * hda); + if (da < 0.0f) + kappa = -kappa; + + for (i = 0; i <= ndivs; i++) { + a = a1 + da * ((float)i / (float)ndivs); + dx = cosf(a); + dy = sinf(a); + nsvg__xformPoint(&x, &y, dx * rx, dy * ry, t); // position + nsvg__xformVec(&tanx, &tany, -dy * rx * kappa, dx * ry * kappa, t); // tangent + if (i > 0) + nsvg__cubicBezTo(p, px + ptanx, py + ptany, x - tanx, y - tany, x, y); + px = x; + py = y; + ptanx = tanx; + ptany = tany; + } + + *cpx = x2; + *cpy = y2; +} + +static void nsvg__parsePath(NSVGparser* p, const char** attr) { + const char* s = NULL; + char cmd = '\0'; + float args[10]; + int nargs; + int rargs = 0; + char initPoint; + float cpx, cpy, cpx2, cpy2; + const char* tmp[4]; + char closedFlag; + int i; + char item[64]; + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "d") == 0) { + s = attr[i + 1]; + } else { + tmp[0] = attr[i]; + tmp[1] = attr[i + 1]; + tmp[2] = 0; + tmp[3] = 0; + nsvg__parseAttribs(p, tmp); + } + } + + if (s) { + nsvg__resetPath(p); + cpx = 0; + cpy = 0; + cpx2 = 0; + cpy2 = 0; + initPoint = 0; + closedFlag = 0; + nargs = 0; + + while (*s) { + item[0] = '\0'; + if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4)) + s = nsvg__getNextPathItemWhenArcFlag(s, item); + if (!*item) + s = nsvg__getNextPathItem(s, item); + if (!*item) + break; + if (cmd != '\0' && nsvg__isCoordinate(item)) { + if (nargs < 10) + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= rargs) { + switch (cmd) { + case 'm': + case 'M': + nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); + // Moveto can be followed by multiple coordinate pairs, + // which should be treated as linetos. + cmd = (cmd == 'm') ? 'l' : 'L'; + rargs = nsvg__getArgsPerElement(cmd); + cpx2 = cpx; + cpy2 = cpy; + initPoint = 1; + break; + case 'l': + case 'L': + nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'H': + case 'h': + nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'V': + case 'v': + nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + case 'C': + case 'c': + nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); + break; + case 'S': + case 's': + nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); + break; + case 'Q': + case 'q': + nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); + break; + case 'T': + case 't': + nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0); + break; + case 'A': + case 'a': + nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); + cpx2 = cpx; + cpy2 = cpy; + break; + default: + if (nargs >= 2) { + cpx = args[nargs - 2]; + cpy = args[nargs - 1]; + cpx2 = cpx; + cpy2 = cpy; + } + break; + } + nargs = 0; + } + } else { + cmd = item[0]; + if (cmd == 'M' || cmd == 'm') { + // Commit path. + if (p->npts > 0) + nsvg__addPath(p, closedFlag); + // Start new subpath. + nsvg__resetPath(p); + closedFlag = 0; + nargs = 0; + } else if (initPoint == 0) { + // Do not allow other commands until initial point has been set (moveTo called once). + cmd = '\0'; + } + if (cmd == 'Z' || cmd == 'z') { + closedFlag = 1; + // Commit path. + if (p->npts > 0) { + // Move current point to first point + cpx = p->pts[0]; + cpy = p->pts[1]; + cpx2 = cpx; + cpy2 = cpy; + nsvg__addPath(p, closedFlag); + } + // Start new subpath. + nsvg__resetPath(p); + nsvg__moveTo(p, cpx, cpy); + closedFlag = 0; + nargs = 0; + } + rargs = nsvg__getArgsPerElement(cmd); + if (rargs == -1) { + // Command not recognized + cmd = '\0'; + rargs = 0; + } + } + } + // Commit path. + if (p->npts) + nsvg__addPath(p, closedFlag); + } + + nsvg__addShape(p); +} + +static void nsvg__parseRect(NSVGparser* p, const char** attr) { + float x = 0.0f; + float y = 0.0f; + float w = 0.0f; + float h = 0.0f; + float rx = -1.0f; // marks not set + float ry = -1.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x") == 0) + x = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y") == 0) + y = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "width") == 0) + w = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p)); + if (strcmp(attr[i], "height") == 0) + h = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) + rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) + ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx < 0.0f && ry > 0.0f) + rx = ry; + if (ry < 0.0f && rx > 0.0f) + ry = rx; + if (rx < 0.0f) + rx = 0.0f; + if (ry < 0.0f) + ry = 0.0f; + if (rx > w / 2.0f) + rx = w / 2.0f; + if (ry > h / 2.0f) + ry = h / 2.0f; + + if (w != 0.0f && h != 0.0f) { + nsvg__resetPath(p); + + if (rx < 0.00001f || ry < 0.0001f) { + nsvg__moveTo(p, x, y); + nsvg__lineTo(p, x + w, y); + nsvg__lineTo(p, x + w, y + h); + nsvg__lineTo(p, x, y + h); + } else { + // Rounded rectangle + nsvg__moveTo(p, x + rx, y); + nsvg__lineTo(p, x + w - rx, y); + nsvg__cubicBezTo(p, x + w - rx * (1 - NSVG_KAPPA90), y, x + w, y + ry * (1 - NSVG_KAPPA90), x + w, y + ry); + nsvg__lineTo(p, x + w, y + h - ry); + nsvg__cubicBezTo(p, x + w, y + h - ry * (1 - NSVG_KAPPA90), x + w - rx * (1 - NSVG_KAPPA90), y + h, x + w - rx, y + h); + nsvg__lineTo(p, x + rx, y + h); + nsvg__cubicBezTo(p, x + rx * (1 - NSVG_KAPPA90), y + h, x, y + h - ry * (1 - NSVG_KAPPA90), x, y + h - ry); + nsvg__lineTo(p, x, y + ry); + nsvg__cubicBezTo(p, x, y + ry * (1 - NSVG_KAPPA90), x + rx * (1 - NSVG_KAPPA90), y, x + rx, y); + } + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseCircle(NSVGparser* p, const char** attr) { + float cx = 0.0f; + float cy = 0.0f; + float r = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) + cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) + cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "r") == 0) + r = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualLength(p))); + } + } + + if (r > 0.0f) { + nsvg__resetPath(p); + + nsvg__moveTo(p, cx + r, cy); + nsvg__cubicBezTo(p, cx + r, cy + r * NSVG_KAPPA90, cx + r * NSVG_KAPPA90, cy + r, cx, cy + r); + nsvg__cubicBezTo(p, cx - r * NSVG_KAPPA90, cy + r, cx - r, cy + r * NSVG_KAPPA90, cx - r, cy); + nsvg__cubicBezTo(p, cx - r, cy - r * NSVG_KAPPA90, cx - r * NSVG_KAPPA90, cy - r, cx, cy - r); + nsvg__cubicBezTo(p, cx + r * NSVG_KAPPA90, cy - r, cx + r, cy - r * NSVG_KAPPA90, cx + r, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseEllipse(NSVGparser* p, const char** attr) { + float cx = 0.0f; + float cy = 0.0f; + float rx = 0.0f; + float ry = 0.0f; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "cx") == 0) + cx = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "cy") == 0) + cy = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "rx") == 0) + rx = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualWidth(p))); + if (strcmp(attr[i], "ry") == 0) + ry = fabsf(nsvg__parseCoordinate(p, attr[i + 1], 0.0f, nsvg__actualHeight(p))); + } + } + + if (rx > 0.0f && ry > 0.0f) { + + nsvg__resetPath(p); + + nsvg__moveTo(p, cx + rx, cy); + nsvg__cubicBezTo(p, cx + rx, cy + ry * NSVG_KAPPA90, cx + rx * NSVG_KAPPA90, cy + ry, cx, cy + ry); + nsvg__cubicBezTo(p, cx - rx * NSVG_KAPPA90, cy + ry, cx - rx, cy + ry * NSVG_KAPPA90, cx - rx, cy); + nsvg__cubicBezTo(p, cx - rx, cy - ry * NSVG_KAPPA90, cx - rx * NSVG_KAPPA90, cy - ry, cx, cy - ry); + nsvg__cubicBezTo(p, cx + rx * NSVG_KAPPA90, cy - ry, cx + rx, cy - ry * NSVG_KAPPA90, cx + rx, cy); + + nsvg__addPath(p, 1); + + nsvg__addShape(p); + } +} + +static void nsvg__parseLine(NSVGparser* p, const char** attr) { + float x1 = 0.0; + float y1 = 0.0; + float x2 = 0.0; + float y2 = 0.0; + int i; + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "x1") == 0) + x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y1") == 0) + y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + if (strcmp(attr[i], "x2") == 0) + x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p)); + if (strcmp(attr[i], "y2") == 0) + y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p)); + } + } + + nsvg__resetPath(p); + + nsvg__moveTo(p, x1, y1); + nsvg__lineTo(p, x2, y2); + + nsvg__addPath(p, 0); + + nsvg__addShape(p); +} + +static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) { + int i; + const char* s; + float args[2]; + int nargs, npts = 0; + char item[64]; + + nsvg__resetPath(p); + + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "points") == 0) { + s = attr[i + 1]; + nargs = 0; + while (*s) { + s = nsvg__getNextPathItem(s, item); + args[nargs++] = (float)nsvg__atof(item); + if (nargs >= 2) { + if (npts == 0) + nsvg__moveTo(p, args[0], args[1]); + else + nsvg__lineTo(p, args[0], args[1]); + nargs = 0; + npts++; + } + } + } + } + } + + nsvg__addPath(p, (char)closeFlag); + + nsvg__addShape(p); +} + +static void nsvg__parseSVG(NSVGparser* p, const char** attr) { + int i; + for (i = 0; attr[i]; i += 2) { + if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "width") == 0) { + p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "height") == 0) { + p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); + } else if (strcmp(attr[i], "viewBox") == 0) { + const char* s = attr[i + 1]; + char buf[64]; + s = nsvg__parseNumber(s, buf, 64); + p->viewMinx = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewMiny = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewWidth = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) + s++; + if (!*s) + return; + s = nsvg__parseNumber(s, buf, 64); + p->viewHeight = nsvg__atof(buf); + } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { + if (strstr(attr[i + 1], "none") != 0) { + // No uniform scaling + p->alignType = NSVG_ALIGN_NONE; + } else { + // Parse X align + if (strstr(attr[i + 1], "xMin") != 0) + p->alignX = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "xMid") != 0) + p->alignX = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "xMax") != 0) + p->alignX = NSVG_ALIGN_MAX; + // Parse X align + if (strstr(attr[i + 1], "yMin") != 0) + p->alignY = NSVG_ALIGN_MIN; + else if (strstr(attr[i + 1], "yMid") != 0) + p->alignY = NSVG_ALIGN_MID; + else if (strstr(attr[i + 1], "yMax") != 0) + p->alignY = NSVG_ALIGN_MAX; + // Parse meet/slice + p->alignType = NSVG_ALIGN_MEET; + if (strstr(attr[i + 1], "slice") != 0) + p->alignType = NSVG_ALIGN_SLICE; + } + } + } + } +} + +static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type) { + int i; + NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); + if (grad == NULL) + return; + memset(grad, 0, sizeof(NSVGgradientData)); + grad->units = NSVG_OBJECT_SPACE; + grad->type = type; + if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) { + grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT); + grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT); + } else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) { + grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT); + } + + nsvg__xformIdentity(grad->xform); + + for (i = 0; attr[i]; i += 2) { + if (strcmp(attr[i], "id") == 0) { + strncpy(grad->id, attr[i + 1], 63); + grad->id[63] = '\0'; + } else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { + if (strcmp(attr[i], "gradientUnits") == 0) { + if (strcmp(attr[i + 1], "objectBoundingBox") == 0) + grad->units = NSVG_OBJECT_SPACE; + else + grad->units = NSVG_USER_SPACE; + } else if (strcmp(attr[i], "gradientTransform") == 0) { + nsvg__parseTransform(grad->xform, attr[i + 1]); + } else if (strcmp(attr[i], "cx") == 0) { + grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "cy") == 0) { + grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "r") == 0) { + grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fx") == 0) { + grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "fy") == 0) { + grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x1") == 0) { + grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y1") == 0) { + grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "x2") == 0) { + grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "y2") == 0) { + grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]); + } else if (strcmp(attr[i], "spreadMethod") == 0) { + if (strcmp(attr[i + 1], "pad") == 0) + grad->spread = NSVG_SPREAD_PAD; + else if (strcmp(attr[i + 1], "reflect") == 0) + grad->spread = NSVG_SPREAD_REFLECT; + else if (strcmp(attr[i + 1], "repeat") == 0) + grad->spread = NSVG_SPREAD_REPEAT; + } else if (strcmp(attr[i], "xlink:href") == 0) { + const char* href = attr[i + 1]; + strncpy(grad->ref, href + 1, 62); + grad->ref[62] = '\0'; + } + } + } + + grad->next = p->gradients; + p->gradients = grad; +} + +static void nsvg__parseGradientStop(NSVGparser* p, const char** attr) { + NSVGattrib* curAttr = nsvg__getAttr(p); + NSVGgradientData* grad; + NSVGgradientStop* stop; + int i, idx; + + curAttr->stopOffset = 0; + curAttr->stopColor = 0; + curAttr->stopOpacity = 1.0f; + + for (i = 0; attr[i]; i += 2) { + nsvg__parseAttr(p, attr[i], attr[i + 1]); + } + + // Add stop to the last gradient. + grad = p->gradients; + if (grad == NULL) + return; + + grad->nstops++; + grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop) * grad->nstops); + if (grad->stops == NULL) + return; + + // Insert + idx = grad->nstops - 1; + for (i = 0; i < grad->nstops - 1; i++) { + if (curAttr->stopOffset < grad->stops[i].offset) { + idx = i; + break; + } + } + if (idx != grad->nstops - 1) { + for (i = grad->nstops - 1; i > idx; i--) + grad->stops[i] = grad->stops[i - 1]; + } + + stop = &grad->stops[idx]; + stop->color = curAttr->stopColor; + stop->color |= (unsigned int)(curAttr->stopOpacity * 255) << 24; + stop->offset = curAttr->stopOffset; +} + +static void nsvg__startElement(void* ud, const char* el, const char** attr) { + NSVGparser* p = (NSVGparser*)ud; + + if (p->defsFlag) { + // Skip everything but gradients in defs + if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } + return; + } + + if (strcmp(el, "g") == 0) { + nsvg__pushAttr(p); + nsvg__parseAttribs(p, attr); + } else if (strcmp(el, "path") == 0) { + if (p->pathFlag) // Do not allow nested paths. + return; + nsvg__pushAttr(p); + nsvg__parsePath(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "rect") == 0) { + nsvg__pushAttr(p); + nsvg__parseRect(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "circle") == 0) { + nsvg__pushAttr(p); + nsvg__parseCircle(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "ellipse") == 0) { + nsvg__pushAttr(p); + nsvg__parseEllipse(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "line") == 0) { + nsvg__pushAttr(p); + nsvg__parseLine(p, attr); + nsvg__popAttr(p); + } else if (strcmp(el, "polyline") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 0); + nsvg__popAttr(p); + } else if (strcmp(el, "polygon") == 0) { + nsvg__pushAttr(p); + nsvg__parsePoly(p, attr, 1); + nsvg__popAttr(p); + } else if (strcmp(el, "linearGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); + } else if (strcmp(el, "radialGradient") == 0) { + nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); + } else if (strcmp(el, "stop") == 0) { + nsvg__parseGradientStop(p, attr); + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 1; + } else if (strcmp(el, "svg") == 0) { + nsvg__parseSVG(p, attr); + } +} + +static void nsvg__endElement(void* ud, const char* el) { + NSVGparser* p = (NSVGparser*)ud; + + if (strcmp(el, "g") == 0) { + nsvg__popAttr(p); + } else if (strcmp(el, "path") == 0) { + p->pathFlag = 0; + } else if (strcmp(el, "defs") == 0) { + p->defsFlag = 0; + } +} + +static void nsvg__content(void* ud, const char* s) { + NSVG_NOTUSED(ud); + NSVG_NOTUSED(s); + // empty +} + +static void nsvg__imageBounds(NSVGparser* p, float* bounds) { + NSVGshape* shape; + shape = p->image->shapes; + if (shape == NULL) { + bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0; + return; + } + bounds[0] = shape->bounds[0]; + bounds[1] = shape->bounds[1]; + bounds[2] = shape->bounds[2]; + bounds[3] = shape->bounds[3]; + for (shape = shape->next; shape != NULL; shape = shape->next) { + bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]); + bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]); + bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]); + bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]); + } +} + +static float nsvg__viewAlign(float content, float container, int type) { + if (type == NSVG_ALIGN_MIN) + return 0; + else if (type == NSVG_ALIGN_MAX) + return container - content; + // mid + return (container - content) * 0.5f; +} + +static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) { + float t[6]; + nsvg__xformSetTranslation(t, tx, ty); + nsvg__xformMultiply(grad->xform, t); + + nsvg__xformSetScale(t, sx, sy); + nsvg__xformMultiply(grad->xform, t); +} + +static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) { + NSVGshape* shape; + NSVGpath* path; + float tx, ty, sx, sy, us, bounds[4], t[6], avgs; + int i; + float* pt; + + // Guess image size if not set completely. + nsvg__imageBounds(p, bounds); + + if (p->viewWidth == 0) { + if (p->image->width > 0) { + p->viewWidth = p->image->width; + } else { + p->viewMinx = bounds[0]; + p->viewWidth = bounds[2] - bounds[0]; + } + } + if (p->viewHeight == 0) { + if (p->image->height > 0) { + p->viewHeight = p->image->height; + } else { + p->viewMiny = bounds[1]; + p->viewHeight = bounds[3] - bounds[1]; + } + } + if (p->image->width == 0) + p->image->width = p->viewWidth; + if (p->image->height == 0) + p->image->height = p->viewHeight; + + tx = -p->viewMinx; + ty = -p->viewMiny; + sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; + sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; + // Unit scaling + us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); + + // Fix aspect ratio + if (p->alignType == NSVG_ALIGN_MEET) { + // fit whole image into viewbox + sx = sy = nsvg__minf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy; + } else if (p->alignType == NSVG_ALIGN_SLICE) { + // fill whole viewbox with image + sx = sy = nsvg__maxf(sx, sy); + tx += nsvg__viewAlign(p->viewWidth * sx, p->image->width, p->alignX) / sx; + ty += nsvg__viewAlign(p->viewHeight * sy, p->image->height, p->alignY) / sy; + } + + // Transform + sx *= us; + sy *= us; + avgs = (sx + sy) / 2.0f; + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + shape->bounds[0] = (shape->bounds[0] + tx) * sx; + shape->bounds[1] = (shape->bounds[1] + ty) * sy; + shape->bounds[2] = (shape->bounds[2] + tx) * sx; + shape->bounds[3] = (shape->bounds[3] + ty) * sy; + for (path = shape->paths; path != NULL; path = path->next) { + path->bounds[0] = (path->bounds[0] + tx) * sx; + path->bounds[1] = (path->bounds[1] + ty) * sy; + path->bounds[2] = (path->bounds[2] + tx) * sx; + path->bounds[3] = (path->bounds[3] + ty) * sy; + for (i = 0; i < path->npts; i++) { + pt = &path->pts[i * 2]; + pt[0] = (pt[0] + tx) * sx; + pt[1] = (pt[1] + ty) * sy; + } + } + + if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->fill.gradient, tx, ty, sx, sy); + memcpy(t, shape->fill.gradient->xform, sizeof(float) * 6); + nsvg__xformInverse(shape->fill.gradient->xform, t); + } + if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) { + nsvg__scaleGradient(shape->stroke.gradient, tx, ty, sx, sy); + memcpy(t, shape->stroke.gradient->xform, sizeof(float) * 6); + nsvg__xformInverse(shape->stroke.gradient->xform, t); + } + + shape->strokeWidth *= avgs; + shape->strokeDashOffset *= avgs; + for (i = 0; i < shape->strokeDashCount; i++) + shape->strokeDashArray[i] *= avgs; + } +} + +static void nsvg__createGradients(NSVGparser* p) { + NSVGshape* shape; + + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + if (shape->fill.type == NSVG_PAINT_UNDEF) { + if (shape->fillGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type); + } + if (shape->fill.type == NSVG_PAINT_UNDEF) { + shape->fill.type = NSVG_PAINT_NONE; + } + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + if (shape->strokeGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type); + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + shape->stroke.type = NSVG_PAINT_NONE; + } + } + } +} + +NSVGimage* nsvgParse(char* input, const char* units, float dpi) { + NSVGparser* p; + NSVGimage* ret = 0; + + p = nsvg__createParser(); + if (p == NULL) { + return NULL; + } + p->dpi = dpi; + + nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); + + // Create gradients after all definitions have been parsed + nsvg__createGradients(p); + + // Scale to viewBox + nsvg__scaleToViewbox(p, units); + + ret = p->image; + p->image = NULL; + + nsvg__deleteParser(p); + + return ret; +} + +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) { + FILE* fp = NULL; + size_t size; + char* data = NULL; + NSVGimage* image = NULL; + + fp = fopen(filename, "rb"); + if (!fp) + goto error; + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + data = (char*)malloc(size + 1); + if (data == NULL) + goto error; + if (fread(data, 1, size, fp) != size) + goto error; + data[size] = '\0'; // Must be null terminated. + fclose(fp); + image = nsvgParse(data, units, dpi); + free(data); + + return image; + +error: + if (fp) + fclose(fp); + if (data) + free(data); + if (image) + nsvgDelete(image); + return NULL; +} + +NSVGpath* nsvgDuplicatePath(NSVGpath* p) { + NSVGpath* res = NULL; + + if (p == NULL) + return NULL; + + res = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (res == NULL) + goto error; + memset(res, 0, sizeof(NSVGpath)); + + res->pts = (float*)malloc(p->npts * 2 * sizeof(float)); + if (res->pts == NULL) + goto error; + memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2); + res->npts = p->npts; + + memcpy(res->bounds, p->bounds, sizeof(p->bounds)); + + res->closed = p->closed; + + return res; + +error: + if (res != NULL) { + free(res->pts); + free(res); + } + return NULL; +} + +void nsvgDelete(NSVGimage* image) { + NSVGshape *snext, *shape; + if (image == NULL) + return; + shape = image->shapes; + while (shape != NULL) { + snext = shape->next; + nsvg__deletePaths(shape->paths); + nsvg__deletePaint(&shape->fill); + nsvg__deletePaint(&shape->stroke); + free(shape); + shape = snext; + } + free(image); +} + +#endif // NANOSVG_IMPLEMENTATION + +#endif // NANOSVG_H \ No newline at end of file diff --git a/include/nanosvgrast.h b/include/nanosvgrast.h new file mode 100644 index 0000000..d067156 --- /dev/null +++ b/include/nanosvgrast.h @@ -0,0 +1,1461 @@ +/* + * Copyright (c) 2013-14 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. + * + * The polygon rasterization is heavily based on stb_truetype rasterizer + * by Sean Barrett - http://nothings.org/ + * + */ + +#ifndef NANOSVGRAST_H +#define NANOSVGRAST_H + +#include "nanosvg.h" + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +extern "C" { +#endif +#endif + +typedef struct NSVGrasterizer NSVGrasterizer; + +/* Example Usage: + // Load SVG + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + + // Create rasterizer (can be used to render multiple images). + struct NSVGrasterizer* rast = nsvgCreateRasterizer(); + // Allocate memory for image + unsigned char* img = malloc(w*h*4); + // Rasterize + nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); +*/ + +// Allocated rasterizer context. +NSVGrasterizer* nsvgCreateRasterizer(void); + +// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) +// r - pointer to rasterizer context +// image - pointer to image to rasterize +// tx,ty - image offset (applied after scaling) +// scale - image scale +// dst - pointer to destination image data, 4 bytes per pixel (RGBA) +// w - width of the image to render +// h - height of the image to render +// stride - number of bytes per scaleline in the destination buffer +void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride); + +// Deletes rasterizer context. +void nsvgDeleteRasterizer(NSVGrasterizer*); + +#ifndef NANOSVGRAST_CPLUSPLUS +#ifdef __cplusplus +} +#endif +#endif + +#ifdef NANOSVGRAST_IMPLEMENTATION + +#include +#include +#include + +#define NSVG__SUBSAMPLES 5 +#define NSVG__FIXSHIFT 10 +#define NSVG__FIX (1 << NSVG__FIXSHIFT) +#define NSVG__FIXMASK (NSVG__FIX - 1) +#define NSVG__MEMPAGE_SIZE 1024 + +typedef struct NSVGedge { + float x0, y0, x1, y1; + int dir; + struct NSVGedge* next; +} NSVGedge; + +typedef struct NSVGpoint { + float x, y; + float dx, dy; + float len; + float dmx, dmy; + unsigned char flags; +} NSVGpoint; + +typedef struct NSVGactiveEdge { + int x, dx; + float ey; + int dir; + struct NSVGactiveEdge* next; +} NSVGactiveEdge; + +typedef struct NSVGmemPage { + unsigned char mem[NSVG__MEMPAGE_SIZE]; + int size; + struct NSVGmemPage* next; +} NSVGmemPage; + +typedef struct NSVGcachedPaint { + signed char type; + char spread; + float xform[6]; + unsigned int colors[256]; +} NSVGcachedPaint; + +struct NSVGrasterizer { + float px, py; + + float tessTol; + float distTol; + + NSVGedge* edges; + int nedges; + int cedges; + + NSVGpoint* points; + int npoints; + int cpoints; + + NSVGpoint* points2; + int npoints2; + int cpoints2; + + NSVGactiveEdge* freelist; + NSVGmemPage* pages; + NSVGmemPage* curpage; + + unsigned char* scanline; + int cscanline; + + unsigned char* bitmap; + int width, height, stride; +}; + +NSVGrasterizer* nsvgCreateRasterizer(void) { + NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer)); + if (r == NULL) + goto error; + memset(r, 0, sizeof(NSVGrasterizer)); + + r->tessTol = 0.25f; + r->distTol = 0.01f; + + return r; + +error: + nsvgDeleteRasterizer(r); + return NULL; +} + +void nsvgDeleteRasterizer(NSVGrasterizer* r) { + NSVGmemPage* p; + + if (r == NULL) + return; + + p = r->pages; + while (p != NULL) { + NSVGmemPage* next = p->next; + free(p); + p = next; + } + + if (r->edges) + free(r->edges); + if (r->points) + free(r->points); + if (r->points2) + free(r->points2); + if (r->scanline) + free(r->scanline); + + free(r); +} + +static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) { + NSVGmemPage* newp; + + // If using existing chain, return the next page in chain + if (cur != NULL && cur->next != NULL) { + return cur->next; + } + + // Alloc new page + newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage)); + if (newp == NULL) + return NULL; + memset(newp, 0, sizeof(NSVGmemPage)); + + // Add to linked list + if (cur != NULL) + cur->next = newp; + else + r->pages = newp; + + return newp; +} + +static void nsvg__resetPool(NSVGrasterizer* r) { + NSVGmemPage* p = r->pages; + while (p != NULL) { + p->size = 0; + p = p->next; + } + r->curpage = r->pages; +} + +static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) { + unsigned char* buf; + if (size > NSVG__MEMPAGE_SIZE) + return NULL; + if (r->curpage == NULL || r->curpage->size + size > NSVG__MEMPAGE_SIZE) { + r->curpage = nsvg__nextPage(r, r->curpage); + } + buf = &r->curpage->mem[r->curpage->size]; + r->curpage->size += size; + return buf; +} + +static int nsvg__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 void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) { + NSVGpoint* pt; + + if (r->npoints > 0) { + pt = &r->points[r->npoints - 1]; + if (nsvg__ptEquals(pt->x, pt->y, x, y, r->distTol)) { + pt->flags = (unsigned char)(pt->flags | flags); + return; + } + } + + if (r->npoints + 1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) + return; + } + + pt = &r->points[r->npoints]; + pt->x = x; + pt->y = y; + pt->flags = (unsigned char)flags; + r->npoints++; +} + +static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt) { + if (r->npoints + 1 > r->cpoints) { + r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64; + r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints); + if (r->points == NULL) + return; + } + r->points[r->npoints] = pt; + r->npoints++; +} + +static void nsvg__duplicatePoints(NSVGrasterizer* r) { + if (r->npoints > r->cpoints2) { + r->cpoints2 = r->npoints; + r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2); + if (r->points2 == NULL) + return; + } + + memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints); + r->npoints2 = r->npoints; +} + +static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) { + NSVGedge* e; + + // Skip horizontal edges + if (y0 == y1) + return; + + if (r->nedges + 1 > r->cedges) { + r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; + r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges); + if (r->edges == NULL) + return; + } + + e = &r->edges[r->nedges]; + r->nedges++; + + if (y0 < y1) { + e->x0 = x0; + e->y0 = y0; + e->x1 = x1; + e->y1 = y1; + e->dir = 1; + } else { + e->x0 = x1; + e->y0 = y1; + e->x1 = x0; + e->y1 = y0; + e->dir = -1; + } +} + +static float nsvg__normalize(float* x, float* y) { + float d = sqrtf((*x) * (*x) + (*y) * (*y)); + if (d > 1e-6f) { + float id = 1.0f / d; + *x *= id; + *y *= id; + } + return d; +} + +static float nsvg__absf(float x) { return x < 0 ? -x : x; } +static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); } + +static void nsvg__flattenCubicBez(NSVGrasterizer* r, 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 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx); + d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx); + + if ((d2 + d3) * (d2 + d3) < r->tessTol * (dx * dx + dy * dy)) { + nsvg__addPathPoint(r, x4, y4, type); + return; + } + + x234 = (x23 + x34) * 0.5f; + y234 = (y23 + y34) * 0.5f; + x1234 = (x123 + x234) * 0.5f; + y1234 = (y123 + y234) * 0.5f; + + nsvg__flattenCubicBez(r, x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1, 0); + nsvg__flattenCubicBez(r, x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1, type); +} + +static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale) { + int i, j; + NSVGpath* path; + + for (path = shape->paths; path != NULL; path = path->next) { + r->npoints = 0; + // Flatten path + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, 0); + for (i = 0; i < path->npts - 1; i += 3) { + float* p = &path->pts[i * 2]; + nsvg__flattenCubicBez(r, p[0] * scale, p[1] * scale, p[2] * scale, p[3] * scale, p[4] * scale, p[5] * scale, p[6] * scale, p[7] * scale, 0, 0); + } + // Close path + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, 0); + // Build edges + for (i = 0, j = r->npoints - 1; i < r->npoints; j = i++) + nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); + } +} + +enum NSVGpointFlags { NSVG_PT_CORNER = 0x01, NSVG_PT_BEVEL = 0x02, NSVG_PT_LEFT = 0x04 }; + +static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + float len = nsvg__normalize(&dx, &dy); + float px = p0->x + dx * len * 0.5f, py = p0->y + dy * len * 0.5f; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) { + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect) { + float w = lineWidth * 0.5f; + float px = p->x - dx * w, py = p->y - dy * w; + float dlx = dy, dly = -dx; + float lx = px - dlx * w, ly = py - dly * w; + float rx = px + dlx * w, ry = py + dly * w; + + nsvg__addEdge(r, lx, ly, rx, ry); + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +#ifndef NSVG_PI +#define NSVG_PI (3.14159265358979323846264338327f) +#endif + +static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect) { + int i; + float w = lineWidth * 0.5f; + float px = p->x, py = p->y; + float dlx = dy, dly = -dx; + float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; + + for (i = 0; i < ncap; i++) { + float a = (float)i / (float)(ncap - 1) * NSVG_PI; + float ax = cosf(a) * w, ay = sinf(a) * w; + float x = px - dlx * ax - dx * ay; + float y = py - dly * ax - dy * ay; + + if (i > 0) + nsvg__addEdge(r, prevx, prevy, x, y); + + prevx = x; + prevy = y; + + if (i == 0) { + lx = x; + ly = y; + } else if (i == ncap - 1) { + rx = x; + ry = y; + } + } + + if (connect) { + nsvg__addEdge(r, left->x, left->y, lx, ly); + nsvg__addEdge(r, rx, ry, right->x, right->y); + } + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w); + float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w); + float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w); + float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w); + + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + + left->x = lx1; + left->y = ly1; + right->x = rx1; + right->y = ry1; +} + +static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float lx0, rx0, lx1, rx1; + float ly0, ry0, ly1, ry1; + + if (p1->flags & NSVG_PT_LEFT) { + lx0 = lx1 = p1->x - p1->dmx * w; + ly0 = ly1 = p1->y - p1->dmy * w; + nsvg__addEdge(r, lx1, ly1, left->x, left->y); + + rx0 = p1->x + (dlx0 * w); + ry0 = p1->y + (dly0 * w); + rx1 = p1->x + (dlx1 * w); + ry1 = p1->y + (dly1 * w); + nsvg__addEdge(r, right->x, right->y, rx0, ry0); + nsvg__addEdge(r, rx0, ry0, rx1, ry1); + } else { + lx0 = p1->x - (dlx0 * w); + ly0 = p1->y - (dly0 * w); + lx1 = p1->x - (dlx1 * w); + ly1 = p1->y - (dly1 * w); + nsvg__addEdge(r, lx0, ly0, left->x, left->y); + nsvg__addEdge(r, lx1, ly1, lx0, ly0); + + rx0 = rx1 = p1->x + p1->dmx * w; + ry0 = ry1 = p1->y + p1->dmy * w; + nsvg__addEdge(r, right->x, right->y, rx1, ry1); + } + + left->x = lx1; + left->y = ly1; + right->x = rx1; + right->y = ry1; +} + +static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap) { + int i, n; + float w = lineWidth * 0.5f; + float dlx0 = p0->dy, dly0 = -p0->dx; + float dlx1 = p1->dy, dly1 = -p1->dx; + float a0 = atan2f(dly0, dlx0); + float a1 = atan2f(dly1, dlx1); + float da = a1 - a0; + float lx, ly, rx, ry; + + if (da < NSVG_PI) + da += NSVG_PI * 2; + if (da > NSVG_PI) + da -= NSVG_PI * 2; + + n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); + if (n < 2) + n = 2; + if (n > ncap) + n = ncap; + + lx = left->x; + ly = left->y; + rx = right->x; + ry = right->y; + + for (i = 0; i < n; i++) { + float u = (float)i / (float)(n - 1); + float a = a0 + u * da; + float ax = cosf(a) * w, ay = sinf(a) * w; + float lx1 = p1->x - ax, ly1 = p1->y - ay; + float rx1 = p1->x + ax, ry1 = p1->y + ay; + + nsvg__addEdge(r, lx1, ly1, lx, ly); + nsvg__addEdge(r, rx, ry, rx1, ry1); + + lx = lx1; + ly = ly1; + rx = rx1; + ry = ry1; + } + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth) { + float w = lineWidth * 0.5f; + float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w); + float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w); + + nsvg__addEdge(r, lx, ly, left->x, left->y); + nsvg__addEdge(r, right->x, right->y, rx, ry); + + left->x = lx; + left->y = ly; + right->x = rx; + right->y = ry; +} + +static int nsvg__curveDivs(float r, float arc, float tol) { + float da = acosf(r / (r + tol)) * 2.0f; + int divs = (int)ceilf(arc / da); + if (divs < 2) + divs = 2; + return divs; +} + +static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) { + int ncap = nsvg__curveDivs(lineWidth * 0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + NSVGpoint left = {0, 0, 0, 0, 0, 0, 0, 0}, right = {0, 0, 0, 0, 0, 0, 0, 0}, firstLeft = {0, 0, 0, 0, 0, 0, 0, 0}, firstRight = {0, 0, 0, 0, 0, 0, 0, 0}; + NSVGpoint *p0, *p1; + int j, s, e; + + // Build stroke edges + if (closed) { + // Looping + p0 = &points[npoints - 1]; + p1 = &points[0]; + s = 0; + e = npoints; + } else { + // Add cap + p0 = &points[0]; + p1 = &points[1]; + s = 1; + e = npoints - 1; + } + + if (closed) { + nsvg__initClosed(&left, &right, p0, p1, lineWidth); + firstLeft = left; + firstRight = right; + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0); + } + + for (j = s; j < e; ++j) { + if (p1->flags & NSVG_PT_CORNER) { + if (lineJoin == NSVG_JOIN_ROUND) + nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap); + else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL)) + nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth); + else + nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth); + } else { + nsvg__straightJoin(r, &left, &right, p1, lineWidth); + } + p0 = p1++; + } + + if (closed) { + // Loop it + nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); + nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); + } else { + // Add cap + float dx = p1->x - p0->x; + float dy = p1->y - p0->y; + nsvg__normalize(&dx, &dy); + if (lineCap == NSVG_CAP_BUTT) + nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_SQUARE) + nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); + else if (lineCap == NSVG_CAP_ROUND) + nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1); + } +} + +static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin) { + int i, j; + NSVGpoint *p0, *p1; + + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + for (i = 0; i < r->npoints; i++) { + // Calculate segment direction and length + p0->dx = p1->x - p0->x; + p0->dy = p1->y - p0->y; + p0->len = nsvg__normalize(&p0->dx, &p0->dy); + // Advance + p0 = p1++; + } + + // calculate joins + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + for (j = 0; j < r->npoints; j++) { + float dlx0, dly0, dlx1, dly1, dmr2, cross; + 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 s2 = 1.0f / dmr2; + if (s2 > 600.0f) { + s2 = 600.0f; + } + p1->dmx *= s2; + p1->dmy *= s2; + } + + // Clear flags, but keep the corner. + p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; + + // Keep track of left turns. + cross = p1->dx * p0->dy - p0->dx * p1->dy; + if (cross > 0.0f) + p1->flags |= NSVG_PT_LEFT; + + // Check to see if the corner needs to be beveled. + if (p1->flags & NSVG_PT_CORNER) { + if ((dmr2 * miterLimit * miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { + p1->flags |= NSVG_PT_BEVEL; + } + } + + p0 = p1++; + } +} + +static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale) { + int i, j, closed; + NSVGpath* path; + NSVGpoint *p0, *p1; + float miterLimit = shape->miterLimit; + int lineJoin = shape->strokeLineJoin; + int lineCap = shape->strokeLineCap; + float lineWidth = shape->strokeWidth * scale; + + for (path = shape->paths; path != NULL; path = path->next) { + // Flatten path + r->npoints = 0; + nsvg__addPathPoint(r, path->pts[0] * scale, path->pts[1] * scale, NSVG_PT_CORNER); + for (i = 0; i < path->npts - 1; i += 3) { + float* p = &path->pts[i * 2]; + nsvg__flattenCubicBez(r, p[0] * scale, p[1] * scale, p[2] * scale, p[3] * scale, p[4] * scale, p[5] * scale, p[6] * scale, p[7] * scale, 0, + NSVG_PT_CORNER); + } + if (r->npoints < 2) + continue; + + closed = path->closed; + + // If the first and last points are the same, remove the last, mark as closed path. + p0 = &r->points[r->npoints - 1]; + p1 = &r->points[0]; + if (nsvg__ptEquals(p0->x, p0->y, p1->x, p1->y, r->distTol)) { + r->npoints--; + p0 = &r->points[r->npoints - 1]; + closed = 1; + } + + if (shape->strokeDashCount > 0) { + int idash = 0, dashState = 1; + float totalDist = 0, dashLen, allDashLen, dashOffset; + NSVGpoint cur; + + if (closed) + nsvg__appendPathPoint(r, r->points[0]); + + // Duplicate points -> points2. + nsvg__duplicatePoints(r); + + r->npoints = 0; + cur = r->points2[0]; + nsvg__appendPathPoint(r, cur); + + // Figure out dash offset. + allDashLen = 0; + for (j = 0; j < shape->strokeDashCount; j++) + allDashLen += shape->strokeDashArray[j]; + if (shape->strokeDashCount & 1) + allDashLen *= 2.0f; + // Find location inside pattern + dashOffset = fmodf(shape->strokeDashOffset, allDashLen); + if (dashOffset < 0.0f) + dashOffset += allDashLen; + + while (dashOffset > shape->strokeDashArray[idash]) { + dashOffset -= shape->strokeDashArray[idash]; + idash = (idash + 1) % shape->strokeDashCount; + } + dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale; + + for (j = 1; j < r->npoints2;) { + float dx = r->points2[j].x - cur.x; + float dy = r->points2[j].y - cur.y; + float dist = sqrtf(dx * dx + dy * dy); + + if ((totalDist + dist) > dashLen) { + // Calculate intermediate point + float d = (dashLen - totalDist) / dist; + float x = cur.x + dx * d; + float y = cur.y + dy * d; + nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); + + // Stroke + if (r->npoints > 1 && dashState) { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } + // Advance dash pattern + dashState = !dashState; + idash = (idash + 1) % shape->strokeDashCount; + dashLen = shape->strokeDashArray[idash] * scale; + // Restart + cur.x = x; + cur.y = y; + cur.flags = NSVG_PT_CORNER; + totalDist = 0.0f; + r->npoints = 0; + nsvg__appendPathPoint(r, cur); + } else { + totalDist += dist; + cur = r->points2[j]; + nsvg__appendPathPoint(r, cur); + j++; + } + } + // Stroke any leftover path + if (r->npoints > 1 && dashState) + nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); + } else { + nsvg__prepareStroke(r, miterLimit, lineJoin); + nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); + } + } +} + +static int nsvg__cmpEdge(const void* p, const void* q) { + const NSVGedge* a = (const NSVGedge*)p; + const NSVGedge* b = (const NSVGedge*)q; + + if (a->y0 < b->y0) + return -1; + if (a->y0 > b->y0) + return 1; + return 0; +} + +static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) { + NSVGactiveEdge* z; + + if (r->freelist != NULL) { + // Restore from freelist. + z = r->freelist; + r->freelist = z->next; + } else { + // Alloc new edge. + z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); + if (z == NULL) + return NULL; + } + + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + // STBTT_assert(e->y0 <= start_point); + // round dx down to avoid going too far + if (dxdy < 0) + z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy)); + else + z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy); + z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); + // z->x -= off_x * FIX; + z->ey = e->y1; + z->next = 0; + z->dir = e->dir; + + return z; +} + +static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z) { + z->next = r->freelist; + r->freelist = z; +} + +static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) { + int i = x0 >> NSVG__FIXSHIFT; + int j = x1 >> NSVG__FIXSHIFT; + if (i < *xmin) + *xmin = i; + if (j > *xmax) + *xmax = j; + if (i < len && j >= 0) { + if (i == j) { + // x0,x1 are the same pixel, so compute combined coverage + scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); + } else { + if (i >= 0) // add antialiasing for x0 + scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); + else + i = -1; // clip + + if (j < len) // add antialiasing for x1 + scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); + else + j = len; // clip + + for (++i; i < j; ++i) // fill pixels between x0 and x1 + scanline[i] = (unsigned char)(scanline[i] + maxWeight); + } + } +} + +// 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 nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) { + // non-zero winding fill + int x0 = 0, w = 0; + + if (fillRule == NSVG_FILLRULE_NONZERO) { + // Non-zero + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; + w += e->dir; + } else { + int x1 = e->x; + w += e->dir; + // if we went to zero, we need to draw + if (w == 0) + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } else if (fillRule == NSVG_FILLRULE_EVENODD) { + // Even-odd + while (e != NULL) { + if (w == 0) { + // if we're currently at zero, we need to record the edge start point + x0 = e->x; + w = 1; + } else { + int x1 = e->x; + w = 0; + nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); + } + e = e->next; + } + } +} + +static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); } + +static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + return ((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16) | ((unsigned int)a << 24); +} + +static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u) { + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (((c0) & 0xff) * (256 - iu) + (((c1) & 0xff) * iu)) >> 8; + int g = (((c0 >> 8) & 0xff) * (256 - iu) + (((c1 >> 8) & 0xff) * iu)) >> 8; + int b = (((c0 >> 16) & 0xff) * (256 - iu) + (((c1 >> 16) & 0xff) * iu)) >> 8; + int a = (((c0 >> 24) & 0xff) * (256 - iu) + (((c1 >> 24) & 0xff) * iu)) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static unsigned int nsvg__applyOpacity(unsigned int c, float u) { + int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f); + int r = (c) & 0xff; + int g = (c >> 8) & 0xff; + int b = (c >> 16) & 0xff; + int a = (((c >> 24) & 0xff) * iu) >> 8; + return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); +} + +static inline int nsvg__div255(int x) { return ((x + 1) * 257) >> 16; } + +static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, float tx, float ty, float scale, NSVGcachedPaint* cache) { + + if (cache->type == NSVG_PAINT_COLOR) { + int i, cr, cg, cb, ca; + cr = cache->colors[0] & 0xff; + cg = (cache->colors[0] >> 8) & 0xff; + cb = (cache->colors[0] >> 16) & 0xff; + ca = (cache->colors[0] >> 24) & 0xff; + + for (i = 0; i < count; i++) { + int r, g, b; + int a = nsvg__div255((int)cover[0] * ca); + int ia = 255 - a; + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + } + } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + float fx, fy, dx, gy; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r, g, b, a, ia; + gy = fx * t[1] + fy * t[3] + t[5]; + c = cache->colors[(int)nsvg__clampf(gy * 255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { + // TODO: spread modes. + // TODO: plenty of opportunities to optimize. + // TODO: focus (fx,fy) + float fx, fy, dx, gx, gy, gd; + float* t = cache->xform; + int i, cr, cg, cb, ca; + unsigned int c; + + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; + dx = 1.0f / scale; + + for (i = 0; i < count; i++) { + int r, g, b, a, ia; + gx = fx * t[0] + fy * t[2] + t[4]; + gy = fx * t[1] + fy * t[3] + t[5]; + gd = sqrtf(gx * gx + gy * gy); + c = cache->colors[(int)nsvg__clampf(gd * 255.0f, 0, 255.0f)]; + cr = (c) & 0xff; + cg = (c >> 8) & 0xff; + cb = (c >> 16) & 0xff; + ca = (c >> 24) & 0xff; + + a = nsvg__div255((int)cover[0] * ca); + ia = 255 - a; + + // Premultiply + r = nsvg__div255(cr * a); + g = nsvg__div255(cg * a); + b = nsvg__div255(cb * a); + + // Blend over + r += nsvg__div255(ia * (int)dst[0]); + g += nsvg__div255(ia * (int)dst[1]); + b += nsvg__div255(ia * (int)dst[2]); + a += nsvg__div255(ia * (int)dst[3]); + + dst[0] = (unsigned char)r; + dst[1] = (unsigned char)g; + dst[2] = (unsigned char)b; + dst[3] = (unsigned char)a; + + cover++; + dst += 4; + fx += dx; + } + } +} + +static void nsvg__rasterizeSortedEdges(NSVGrasterizer* r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) { + NSVGactiveEdge* active = NULL; + int y, s; + int e = 0; + int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int xmin, xmax; + + for (y = 0; y < r->height; y++) { + memset(r->scanline, 0, r->width); + xmin = r->width; + xmax = 0; + for (s = 0; s < NSVG__SUBSAMPLES; ++s) { + // find center of pixel for this scanline + float scany = (float)(y * NSVG__SUBSAMPLES + s) + 0.5f; + NSVGactiveEdge** step = &active; + + // update all active edges; + // remove all active edges that terminate before the center of this scanline + while (*step) { + NSVGactiveEdge* z = *step; + if (z->ey <= scany) { + *step = z->next; // delete from list + // NSVG__assert(z->valid); + nsvg__freeActive(r, 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) { + NSVGactiveEdge* t = *step; + NSVGactiveEdge* 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 < r->nedges && r->edges[e].y0 <= scany) { + if (r->edges[e].y1 > scany) { + NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); + if (z == NULL) + break; + // 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 + NSVGactiveEdge* 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 non-zero fashion + if (active != NULL) + nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); + } + // Blit + if (xmin < 0) + xmin = 0; + if (xmax > r->width - 1) + xmax = r->width - 1; + if (xmin <= xmax) { + nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin * 4, xmax - xmin + 1, &r->scanline[xmin], xmin, y, tx, ty, scale, cache); + } + } +} + +static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) { + int x, y; + + // Unpremultiply + for (y = 0; y < h; y++) { + unsigned char* row = &image[y * stride]; + for (x = 0; x < w; x++) { + int r = row[0], g = row[1], b = row[2], a = row[3]; + if (a != 0) { + row[0] = (unsigned char)(r * 255 / a); + row[1] = (unsigned char)(g * 255 / a); + row[2] = (unsigned char)(b * 255 / a); + } + row += 4; + } + } + + // Defringe + for (y = 0; y < h; y++) { + unsigned char* row = &image[y * stride]; + for (x = 0; x < w; x++) { + int r = 0, g = 0, b = 0, a = row[3], n = 0; + if (a == 0) { + if (x - 1 > 0 && row[-1] != 0) { + r += row[-4]; + g += row[-3]; + b += row[-2]; + n++; + } + if (x + 1 < w && row[7] != 0) { + r += row[4]; + g += row[5]; + b += row[6]; + n++; + } + if (y - 1 > 0 && row[-stride + 3] != 0) { + r += row[-stride]; + g += row[-stride + 1]; + b += row[-stride + 2]; + n++; + } + if (y + 1 < h && row[stride + 3] != 0) { + r += row[stride]; + g += row[stride + 1]; + b += row[stride + 2]; + n++; + } + if (n > 0) { + row[0] = (unsigned char)(r / n); + row[1] = (unsigned char)(g / n); + row[2] = (unsigned char)(b / n); + } + } + row += 4; + } + } +} + +static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity) { + int i, j; + NSVGgradient* grad; + + cache->type = paint->type; + + if (paint->type == NSVG_PAINT_COLOR) { + cache->colors[0] = nsvg__applyOpacity(paint->color, opacity); + return; + } + + grad = paint->gradient; + + cache->spread = grad->spread; + memcpy(cache->xform, grad->xform, sizeof(float) * 6); + + if (grad->nstops == 0) { + for (i = 0; i < 256; i++) + cache->colors[i] = 0; + } else if (grad->nstops == 1) { + unsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity); + for (i = 0; i < 256; i++) + cache->colors[i] = color; + } else { + unsigned int ca, cb = 0; + float ua, ub, du, u; + int ia, ib, count; + + ca = nsvg__applyOpacity(grad->stops[0].color, opacity); + ua = nsvg__clampf(grad->stops[0].offset, 0, 1); + ub = nsvg__clampf(grad->stops[grad->nstops - 1].offset, ua, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + for (i = 0; i < ia; i++) { + cache->colors[i] = ca; + } + + for (i = 0; i < grad->nstops - 1; i++) { + ca = nsvg__applyOpacity(grad->stops[i].color, opacity); + cb = nsvg__applyOpacity(grad->stops[i + 1].color, opacity); + ua = nsvg__clampf(grad->stops[i].offset, 0, 1); + ub = nsvg__clampf(grad->stops[i + 1].offset, 0, 1); + ia = (int)(ua * 255.0f); + ib = (int)(ub * 255.0f); + count = ib - ia; + if (count <= 0) + continue; + u = 0; + du = 1.0f / (float)count; + for (j = 0; j < count; j++) { + cache->colors[ia + j] = nsvg__lerpRGBA(ca, cb, u); + u += du; + } + } + + for (i = ib; i < 256; i++) + cache->colors[i] = cb; + } +} + +/* +static void dumpEdges(NSVGrasterizer* r, const char* name) +{ + float xmin = 0, xmax = 0, ymin = 0, ymax = 0; + NSVGedge *e = NULL; + int i; + if (r->nedges == 0) return; + FILE* fp = fopen(name, "w"); + if (fp == NULL) return; + + xmin = xmax = r->edges[0].x0; + ymin = ymax = r->edges[0].y0; + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + xmin = nsvg__minf(xmin, e->x0); + xmin = nsvg__minf(xmin, e->x1); + xmax = nsvg__maxf(xmax, e->x0); + xmax = nsvg__maxf(xmax, e->x1); + ymin = nsvg__minf(ymin, e->y0); + ymin = nsvg__minf(ymin, e->y1); + ymax = nsvg__maxf(ymax, e->y0); + ymax = nsvg__maxf(ymax, e->y1); + } + + fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); + + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); + } + + for (i = 0; i < r->npoints; i++) { + if (i+1 < r->npoints) + fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, +r->points[i+1].y); fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : +"#0f0"); + } + + fprintf(fp, ""); + fclose(fp); +} +*/ + +void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride) { + NSVGshape* shape = NULL; + NSVGedge* e = NULL; + NSVGcachedPaint cache; + int i; + int j; + unsigned char paintOrder; + + r->bitmap = dst; + r->width = w; + r->height = h; + r->stride = stride; + + if (w > r->cscanline) { + r->cscanline = w; + r->scanline = (unsigned char*)realloc(r->scanline, w); + if (r->scanline == NULL) + return; + } + + for (i = 0; i < h; i++) + memset(&dst[i * stride], 0, w * 4); + + for (shape = image->shapes; shape != NULL; shape = shape->next) { + if (!(shape->flags & NSVG_FLAGS_VISIBLE)) + continue; + + for (j = 0; j < 3; j++) { + paintOrder = (shape->paintOrder >> (2 * j)) & 0x03; + + if (paintOrder == NSVG_PAINT_FILL && shape->fill.type != NSVG_PAINT_NONE) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShape(r, shape, scale); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->fill, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx, ty, scale, &cache, shape->fillRule); + } + if (paintOrder == NSVG_PAINT_STROKE && shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { + nsvg__resetPool(r); + r->freelist = NULL; + r->nedges = 0; + + nsvg__flattenShapeStroke(r, shape, scale); + + // dumpEdges(r, "edge.svg"); + + // Scale and translate edges + for (i = 0; i < r->nedges; i++) { + e = &r->edges[i]; + e->x0 = tx + e->x0; + e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; + e->x1 = tx + e->x1; + e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; + } + + // Rasterize edges + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + + // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + nsvg__initPaint(&cache, &shape->stroke, shape->opacity); + + nsvg__rasterizeSortedEdges(r, tx, ty, scale, &cache, NSVG_FILLRULE_NONZERO); + } + } + } + + nsvg__unpremultiplyAlpha(dst, w, h, stride); + + r->bitmap = NULL; + r->width = 0; + r->height = 0; + r->stride = 0; +} + +#endif // NANOSVGRAST_IMPLEMENTATION + +#endif // NANOSVGRAST_H \ No newline at end of file diff --git a/include/tinyxml2 b/include/tinyxml2 deleted file mode 160000 index e6caeae..0000000 --- a/include/tinyxml2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e6caeae85799003f4ca74ff26ee16a789bc2af48 diff --git a/src/COMMON.h b/src/COMMON.h deleted file mode 100644 index 9c8948c..0000000 --- a/src/COMMON.h +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -typedef float f32; -typedef double f64; - -#define PI (GLM_PI) -#define TAU (PI * 2) - -using namespace glm; - -#define PREFERENCES_DIRECTORY "anm2ed" - -#define ROUND_NEAREST_MULTIPLE(value, multiple) (roundf((value) / (multiple)) * (multiple)) -#define FLOAT_TO_U8(x) (static_cast((x) * 255.0f)) -#define U8_TO_FLOAT(x) ((x) / 255.0f) -#define PERCENT_TO_UNIT(x) (x / 100.0f) -#define UNIT_TO_PERCENT(x) (x * 100.0f) -#define SECOND 1000.0f -#define TICK_DELAY (SECOND / 30.0) -#define UPDATE_DELAY (SECOND / 120.0) -#define ID_NONE -1 -#define INDEX_NONE -1 -#define VALUE_NONE -1 -#define TIME_NONE -1.0f -#define GL_ID_NONE 0 - -#ifdef _WIN32 - #define POPEN _popen - #define PCLOSE _pclose - #define PWRITE_MODE "wb" - #define PREAD_MODE "r" -#else - #define POPEN popen - #define PCLOSE pclose - #define PWRITE_MODE "w" - #define PREAD_MODE "r" -#endif - -static const GLuint GL_TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0}; -static const vec4 COLOR_RED = {1.0f, 0.0f, 0.0f, 1.0f}; -static const vec4 COLOR_GREEN = {0.0f, 1.0f, 0.0f, 1.0f}; -static const vec4 COLOR_BLUE = {0.0f, 0.0f, 1.0f, 1.0f}; -static const vec4 COLOR_PINK = {1.0f, 0.0f, 1.0f, 1.0f}; -static const vec4 COLOR_OPAQUE = {1.0f, 1.0f, 1.0f, 1.0f}; -static const vec4 COLOR_TRANSPARENT = {0.0f, 0.0f, 0.0f, 0.0f}; -static const vec3 COLOR_OFFSET_NONE = {0.0f, 0.0f, 0.0f}; - -static inline std::string preferences_path_get(void) -{ - char* preferencesPath = SDL_GetPrefPath("", PREFERENCES_DIRECTORY); - std::string preferencesPathString = preferencesPath; - SDL_free(preferencesPath); - return preferencesPathString; -} - -static inline bool string_to_bool(const std::string& string) -{ - if (string == "1") return true; - - std::string lower = string; - std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); - - return lower == "true"; -} - -static inline std::string string_quote(const std::string& string) -{ - return "\"" + string + "\""; -} - -static inline std::string string_to_lowercase(std::string string) { - std::transform - ( - string.begin(), string.end(), string.begin(), - [](u8 character){ return std::tolower(character); } - ); - return string; -} - -static inline std::string string_backslash_replace(std::string string) -{ - for (char& character : string) - if (character == '\\') - character = '/'; - return string; -} - -#define FLOAT_FORMAT_MAX_DECIMALS 5 -#define FLOAT_FORMAT_EPSILON 1e-5f -static constexpr f32 FLOAT_FORMAT_POW10[] = { - 1.f, - 10.f, - 100.f, - 1000.f, - 10000.f, - 100000.f -}; - -static inline s32 f32_decimals_needed(f32 value) -{ - for (s32 decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) - { - f32 scale = FLOAT_FORMAT_POW10[decimalCount]; - f32 rounded = roundf(value * scale) / scale; - if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) - return decimalCount; - } - return FLOAT_FORMAT_MAX_DECIMALS; -} - -static inline const char* f32_format_get(f32 value) -{ - static std::string formatString; - const s32 decimalCount = f32_decimals_needed(value); - formatString = (decimalCount == 0) - ? "%.0f" - : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); -} - -static inline const char* vec2_format_get(const vec2& value) -{ - static std::string formatString; - const s32 decimalCountX = f32_decimals_needed(value.x); - const s32 decimalCountY = f32_decimals_needed(value.y); - const s32 decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; - formatString = (decimalCount == 0) - ? "%.0f" - : ("%." + std::to_string(decimalCount) + "f"); - return formatString.c_str(); -} - -static inline std::string working_directory_from_file_set(const std::string& path) -{ - std::filesystem::path filePath = path; - std::filesystem::path parentPath = filePath.parent_path(); - std::filesystem::current_path(parentPath); - return parentPath.string(); -}; - -static inline std::string path_extension_change(const std::string& path, const std::string& extension) -{ - std::filesystem::path filePath(path); - filePath.replace_extension(extension); - return filePath.string(); -} - -static inline bool path_is_extension(const std::string& path, const std::string& extension) -{ - auto e = std::filesystem::path(path).extension().string(); - std::transform(e.begin(), e.end(), e.begin(), ::tolower); - return e == ("." + extension); -} - -static inline bool path_exists(const std::filesystem::path& pathCheck) -{ - std::error_code errorCode; - return std::filesystem::exists(pathCheck, errorCode) && ((void)std::filesystem::status(pathCheck, errorCode), !errorCode); -} - -static inline bool path_is_valid(const std::filesystem::path& pathCheck) -{ - namespace fs = std::filesystem; - std::error_code ec; - - if (fs::is_directory(pathCheck, ec)) return false; - - fs::path parentDir = pathCheck.has_parent_path() ? pathCheck.parent_path() : fs::path("."); - if (!fs::is_directory(parentDir, ec)) return false; - - bool existedBefore = fs::exists(pathCheck, ec); - std::ofstream testStream(pathCheck, std::ios::app | std::ios::binary); - bool isValid = testStream.is_open(); - testStream.close(); - - if (!existedBefore && isValid) - fs::remove(pathCheck, ec); - - return isValid; -} - -static inline s32 string_to_enum(const std::string& string, const char* const* array, s32 n) -{ - for (s32 i = 0; i < n; i++) - if (string == array[i]) - return i; - return -1; -}; - -template -T& dummy_value() -{ - static T value{}; - return value; -} - -template -static inline s32 map_next_id_get(const std::map& map) -{ - s32 id = 0; - - for (const auto& [key, value] : map) - { - if (key != id) - break; - ++id; - } - - return id; -} - -template -static inline auto map_find(Map& map, typename Map::key_type id) - -> typename Map::mapped_type* -{ - if (auto it = map.find(id); it != map.end()) - return &it->second; - return nullptr; -} - -template -static inline void map_swap(Map& map, const Key& key1, const Key& key2) -{ - if (key1 == key2) - return; - - auto it1 = map.find(key1); - auto it2 = map.find(key2); - - if (it1 != map.end() && it2 != map.end()) - { - using std::swap; - swap(it1->second, it2->second); - } - else if (it1 != map.end()) - { - map[key2] = std::move(it1->second); - map.erase(it1); - } - else if (it2 != map.end()) - { - map[key1] = std::move(it2->second); - map.erase(it2); - } -}; - -template -static inline void map_insert_shift(std::map& map, s32 index, const T& value) -{ - const s32 insertIndex = index + 1; - - std::vector> toShift; - for (auto it = map.rbegin(); it != map.rend(); ++it) - { - if (it->first < insertIndex) - break; - toShift.emplace_back(it->first + 1, std::move(it->second)); - } - - for (const auto& [newKey, _] : toShift) - map.erase(newKey - 1); - - for (auto& [newKey, val] : toShift) - map[newKey] = std::move(val); - - map[insertIndex] = value; -} - -template -void vector_value_erase(std::vector& v, const T& value) -{ - v.erase(std::remove(v.begin(), v.end(), value), v.end()); -} - -template -void vector_value_swap(std::vector& v, const T& a, const T& b) -{ - for (auto& element : v) - { - if (element == a) element = b; - else if (element == b) element = a; - } -} - -static inline mat4 quad_model_get(vec2 size = {}, vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), f32 rotation = {}) -{ - vec2 scaleAbsolute = glm::abs(scale); - vec2 scaleSign = glm::sign(scale); - vec2 pivotScaled = pivot * scaleAbsolute; - vec2 sizeScaled = size * scaleAbsolute; - - mat4 model(1.0f); - model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); - model = glm::translate(model, vec3(pivotScaled, 0.0f)); - model = glm::scale(model, vec3(scaleSign, 1.0f)); - model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); - model = glm::translate(model, vec3(-pivotScaled, 0.0f)); - model = glm::scale(model, vec3(sizeScaled, 1.0f)); - return model; -} - -static inline mat4 quad_model_parent_get(vec2 position = {}, vec2 pivot = {}, vec2 scale = vec2(1.0f), f32 rotation = {}) -{ - vec2 scaleSign = glm::sign(scale); - vec2 scaleAbsolute = glm::abs(scale); - f32 handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; - - mat4 local(1.0f); - local = glm::translate(local, vec3(pivot, 0.0f)); - local = glm::scale(local, vec3(scaleSign, 1.0f)); - local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); - local = glm::translate(local, vec3(-pivot, 0.0f)); - local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); - - return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; -} - -#define DEFINE_STRING_TO_ENUM_FUNCTION(function, enumType, stringArray, count) \ - static inline enumType function(const std::string& string) \ - { \ - return static_cast(string_to_enum(string, stringArray, count)); \ - }; - -#define DATATYPE_LIST \ - X(TYPE_INT, s32) \ - X(TYPE_BOOL, bool) \ - X(TYPE_FLOAT, f32) \ - X(TYPE_STRING, std::string) \ - X(TYPE_IVEC2, ivec2) \ - X(TYPE_IVEC2_WH, ivec2) \ - X(TYPE_VEC2, vec2) \ - X(TYPE_VEC2_WH, vec2) \ - X(TYPE_VEC3, vec3) \ - X(TYPE_VEC4, vec4) - -enum DataType -{ - #define X(symbol, ctype) symbol, - DATATYPE_LIST - #undef X -}; - -#define DATATYPE_TO_CTYPE(dt) DATATYPE_CTYPE_##dt -#define X(symbol, ctype) typedef ctype DATATYPE_CTYPE_##symbol; -DATATYPE_LIST -#undef X - -enum OriginType -{ - ORIGIN_TOP_LEFT, - ORIGIN_CENTER -}; \ No newline at end of file diff --git a/src/PACKED.h b/src/PACKED.h deleted file mode 100644 index d161fb2..0000000 --- a/src/PACKED.h +++ /dev/null @@ -1,347 +0,0 @@ -#pragma once - -#include "COMMON.h" - -const u8 TEXTURE_ATLAS[] = -{ - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xa0, - 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x5e, 0x74, 0xbf, 0x00, 0x00, 0x00, - 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, - 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0x50, 0x4c, - 0x54, 0x45, 0x00, 0x00, 0x00, 0x76, 0x76, 0x76, 0xff, 0xff, 0xff, 0x60, - 0x60, 0x60, 0xff, 0xff, 0xff, 0x3e, 0xd5, 0x47, 0x6d, 0x00, 0x00, 0x00, - 0x03, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0xfa, 0x76, 0xc4, 0xde, - 0x00, 0x00, 0x04, 0x62, 0x49, 0x44, 0x41, 0x54, 0x58, 0xc3, 0xed, 0x59, - 0x5b, 0x6e, 0x24, 0x37, 0x0c, 0x2c, 0x80, 0xbc, 0x40, 0xee, 0x90, 0x03, - 0x10, 0x20, 0x0f, 0xc0, 0x80, 0x75, 0xff, 0x33, 0xe5, 0x83, 0xa2, 0x5a, - 0x63, 0xcf, 0xae, 0xa7, 0x37, 0xb1, 0x03, 0x6c, 0xac, 0x0f, 0x77, 0x6b, - 0x5a, 0xd5, 0x7c, 0x15, 0x49, 0xb5, 0x0c, 0xfc, 0xc2, 0x20, 0x9f, 0xff, - 0xae, 0xd9, 0xd7, 0x28, 0x00, 0xe0, 0xb1, 0x9e, 0x04, 0x40, 0x9a, 0x92, - 0x76, 0xac, 0x27, 0xf3, 0x78, 0x21, 0xbd, 0x00, 0x01, 0xa0, 0x04, 0x98, - 0xd0, 0x46, 0x26, 0x00, 0x04, 0x49, 0xe8, 0x9e, 0x36, 0xc0, 0x95, 0x80, - 0x2e, 0x51, 0x64, 0xdf, 0xee, 0x15, 0xa4, 0x92, 0x83, 0x58, 0x2a, 0x29, - 0x4b, 0xd8, 0x00, 0x9d, 0x17, 0xf6, 0x02, 0xc9, 0x56, 0x68, 0xe6, 0x6d, - 0x4b, 0xbf, 0xa2, 0x67, 0x4c, 0x4d, 0x35, 0xec, 0xb5, 0x89, 0x41, 0x24, - 0x9e, 0x01, 0x94, 0xd0, 0xd4, 0xb6, 0x34, 0x35, 0x7b, 0x81, 0x78, 0x90, - 0xe5, 0xf6, 0x08, 0x28, 0x40, 0x13, 0xcc, 0x13, 0x50, 0x08, 0x03, 0x20, - 0xee, 0x51, 0xee, 0x06, 0x48, 0xfb, 0x8e, 0x61, 0x64, 0x02, 0x9a, 0x4a, - 0x1c, 0x00, 0xe1, 0xf2, 0xb8, 0xb8, 0xbb, 0x1b, 0x80, 0x48, 0xad, 0xb6, - 0x75, 0x59, 0xcf, 0x04, 0xda, 0x4b, 0x00, 0x12, 0x03, 0x30, 0x77, 0x37, - 0x33, 0x21, 0x01, 0xd2, 0xae, 0xc0, 0x75, 0xd4, 0x2e, 0x40, 0xb0, 0x00, - 0x40, 0x44, 0xc4, 0x45, 0xa0, 0x4c, 0x40, 0x99, 0x17, 0x60, 0x02, 0x37, - 0x5e, 0xd2, 0x15, 0x5f, 0x98, 0x99, 0xd9, 0x13, 0xc0, 0xa2, 0x86, 0xb4, - 0xdf, 0xed, 0x22, 0x8d, 0x88, 0x00, 0x10, 0x5a, 0xff, 0xe1, 0xc7, 0xe4, - 0x83, 0xe1, 0x8b, 0xc6, 0xd0, 0x5c, 0xde, 0x48, 0x94, 0x07, 0x72, 0x5f, - 0xf3, 0xa1, 0xf9, 0xdb, 0xe7, 0x93, 0x17, 0xc1, 0xa6, 0x80, 0x93, 0xa4, - 0x5f, 0x9c, 0x92, 0xe5, 0x13, 0xbc, 0x71, 0x2f, 0x0a, 0x00, 0x02, 0x08, - 0x02, 0xac, 0xcd, 0x5a, 0x09, 0xba, 0xb3, 0xec, 0x12, 0x45, 0x77, 0x27, - 0x81, 0x26, 0x28, 0x40, 0xeb, 0x3c, 0x19, 0x40, 0x3f, 0xb7, 0x2d, 0x4a, - 0xe8, 0x1e, 0xa4, 0x0d, 0x40, 0x3a, 0x4f, 0x6c, 0xab, 0xd4, 0xcf, 0x01, - 0x68, 0xb9, 0x47, 0x42, 0xcb, 0x9d, 0x15, 0x39, 0x80, 0xc9, 0x93, 0xa1, - 0xf9, 0x7e, 0x2e, 0x15, 0x51, 0x15, 0xa6, 0xe5, 0x41, 0x8f, 0x44, 0x42, - 0xb3, 0x01, 0x4a, 0x68, 0x0e, 0xcd, 0xf7, 0x73, 0x9a, 0x6a, 0xa6, 0x30, - 0xd2, 0x59, 0xae, 0xd5, 0x00, 0xd9, 0x79, 0x32, 0x34, 0xd7, 0x72, 0x96, - 0x47, 0x42, 0x52, 0x4d, 0x52, 0x4d, 0x4b, 0x09, 0x8c, 0x4a, 0x57, 0x9e, - 0xc0, 0xdc, 0x1d, 0x80, 0x66, 0xd0, 0xa1, 0x09, 0x28, 0x48, 0x24, 0x84, - 0x2c, 0xf7, 0x65, 0x34, 0x09, 0x21, 0x13, 0x4e, 0x53, 0x29, 0xb1, 0x9e, - 0x97, 0x39, 0x01, 0x48, 0x01, 0x61, 0x00, 0xe9, 0xee, 0xed, 0x56, 0x8d, - 0x4a, 0x90, 0x10, 0xa7, 0x81, 0x66, 0x6b, 0x6e, 0xe2, 0xb4, 0x0e, 0x6d, - 0x01, 0x50, 0xba, 0xaf, 0xc0, 0x95, 0x66, 0x20, 0x08, 0x67, 0x39, 0x28, - 0xc7, 0x3c, 0xfd, 0x19, 0x35, 0x4c, 0x4d, 0xb2, 0xa9, 0x01, 0x53, 0x24, - 0xd4, 0x24, 0x05, 0x24, 0xf9, 0xc0, 0xbf, 0x83, 0x5c, 0x64, 0xcf, 0xdd, - 0xcf, 0x8c, 0xb9, 0xe6, 0xbf, 0xca, 0xf7, 0xb9, 0xbe, 0xdc, 0x1f, 0xd6, - 0x75, 0xa9, 0xa6, 0x49, 0x4d, 0x5e, 0x57, 0x00, 0x40, 0x57, 0xc2, 0x29, - 0xa1, 0x47, 0xed, 0xc6, 0x94, 0x9d, 0x7d, 0x5d, 0xc5, 0xcd, 0xde, 0xab, - 0xb6, 0xd8, 0xa9, 0xfd, 0x86, 0x5d, 0x11, 0x01, 0x40, 0xcd, 0xed, 0xf4, - 0xce, 0x2a, 0xba, 0xec, 0x6a, 0xd7, 0x45, 0x71, 0xcc, 0x4a, 0x00, 0x28, - 0x0a, 0x80, 0x0c, 0x93, 0x52, 0x6c, 0x96, 0xae, 0xc2, 0xa5, 0x00, 0xa2, - 0x25, 0x6d, 0x0d, 0x82, 0x06, 0x68, 0x16, 0x10, 0x9a, 0x9a, 0x88, 0x82, - 0xa6, 0x76, 0xfa, 0xa5, 0x2e, 0x09, 0x87, 0x4a, 0xc5, 0x4a, 0x80, 0x99, - 0x9a, 0xba, 0x12, 0x91, 0xa4, 0x76, 0x8c, 0xba, 0x09, 0xc5, 0xa9, 0x92, - 0x06, 0x03, 0xcf, 0x01, 0xd9, 0x12, 0x98, 0x38, 0x55, 0x6a, 0x01, 0x4f, - 0x55, 0xa2, 0x32, 0xb5, 0x99, 0xd5, 0x2a, 0x69, 0x26, 0xd0, 0x02, 0xde, - 0x19, 0x2d, 0x4c, 0xb0, 0x7b, 0x76, 0x8e, 0x77, 0x3a, 0x6f, 0xb4, 0xf2, - 0x0d, 0xe9, 0xc6, 0xad, 0xb9, 0xda, 0xf4, 0x14, 0x9c, 0xbe, 0x67, 0xc6, - 0x73, 0x4e, 0x29, 0x93, 0xcc, 0x01, 0xe4, 0x05, 0xe0, 0xdb, 0x2d, 0xc2, - 0xa6, 0xc6, 0x29, 0x61, 0xab, 0x24, 0x91, 0x3f, 0x22, 0x5f, 0xef, 0x08, - 0x94, 0x4c, 0x6a, 0x02, 0xd4, 0xa4, 0xe6, 0x43, 0xe9, 0xbe, 0x4d, 0xef, - 0x7f, 0x3a, 0x0e, 0x39, 0xba, 0xb3, 0xf7, 0xb1, 0x8b, 0x2d, 0xfd, 0xd4, - 0xa2, 0x1e, 0x15, 0x5b, 0xf7, 0xf4, 0x01, 0x58, 0xff, 0xb0, 0xe6, 0x52, - 0x5c, 0x3d, 0xe2, 0xec, 0x19, 0xd0, 0xea, 0x38, 0x09, 0x6b, 0x3d, 0x94, - 0x58, 0x8b, 0x62, 0xf7, 0x83, 0x69, 0x03, 0x4c, 0xb0, 0x37, 0x0c, 0x10, - 0xa6, 0x5a, 0x2f, 0xf4, 0xae, 0x64, 0x50, 0xb0, 0xb0, 0x38, 0x88, 0x7d, - 0x33, 0xb5, 0x27, 0x3c, 0xb5, 0x2b, 0x9f, 0x04, 0xe9, 0x6d, 0xad, 0xda, - 0x74, 0x9c, 0x01, 0x24, 0x9c, 0x4e, 0x27, 0x84, 0x4e, 0x76, 0x4a, 0x1b, - 0xbb, 0x75, 0x69, 0xd7, 0xd9, 0xde, 0xb5, 0xf5, 0x0e, 0x46, 0x89, 0x01, - 0x28, 0x49, 0x46, 0x02, 0x10, 0xea, 0x08, 0xb0, 0x8c, 0xe5, 0x19, 0x4d, - 0x9d, 0xbd, 0x59, 0x1b, 0x0c, 0x05, 0xd9, 0xfc, 0x0e, 0xe6, 0x08, 0xd0, - 0x1d, 0x87, 0x01, 0x00, 0x70, 0x77, 0x77, 0x87, 0x82, 0xac, 0x55, 0x41, - 0x29, 0x23, 0xe0, 0x08, 0xc0, 0x0e, 0x87, 0x01, 0x02, 0x81, 0x92, 0x5e, - 0xab, 0xc4, 0xb6, 0x1f, 0x1e, 0x0a, 0xc4, 0xb2, 0xe1, 0x04, 0xa4, 0x7a, - 0x0d, 0xab, 0x97, 0x26, 0x79, 0xf1, 0x9d, 0xd7, 0x26, 0x76, 0x01, 0xba, - 0x26, 0x74, 0xe0, 0xcb, 0x05, 0x86, 0x38, 0x13, 0xe4, 0x00, 0x2c, 0x1b, - 0x00, 0x19, 0x80, 0xb8, 0xd9, 0x63, 0xc9, 0x9c, 0x48, 0x7f, 0x15, 0xdd, - 0xf1, 0x3e, 0xbd, 0x24, 0x5f, 0x04, 0x0c, 0x68, 0x95, 0xd3, 0xb1, 0xc0, - 0xba, 0xbe, 0x82, 0xf5, 0x03, 0xc0, 0x2a, 0xa7, 0xcc, 0x8f, 0x00, 0x57, - 0x5d, 0x99, 0x52, 0xf1, 0x1a, 0x40, 0xb9, 0xdb, 0x74, 0xfe, 0x04, 0x70, - 0xd4, 0xc6, 0xb2, 0x01, 0x74, 0x33, 0x69, 0x00, 0xd7, 0xde, 0x6f, 0xae, - 0xdb, 0x06, 0xd9, 0x1f, 0x4d, 0x9d, 0x9b, 0x3f, 0x03, 0x6c, 0x22, 0xd4, - 0x00, 0xea, 0xc7, 0x80, 0x63, 0x38, 0x73, 0x01, 0xca, 0x2e, 0x95, 0xdc, - 0x59, 0xee, 0x57, 0x3e, 0x1c, 0x05, 0x79, 0xdc, 0xba, 0x32, 0xf5, 0xb9, - 0xd1, 0xba, 0xea, 0xed, 0xe9, 0xd6, 0x36, 0xfe, 0x63, 0xc0, 0xaa, 0x83, - 0x6b, 0xfd, 0x0b, 0x80, 0xfe, 0xd4, 0xc0, 0xec, 0x0a, 0xc4, 0x6d, 0xed, - 0x10, 0x1e, 0x36, 0x3b, 0xa7, 0x4a, 0xaf, 0x91, 0xf5, 0xb1, 0x0b, 0xdd, - 0x18, 0xfe, 0x66, 0xd8, 0xfb, 0x57, 0x3f, 0x07, 0x8c, 0x05, 0x1f, 0x02, - 0x82, 0x13, 0xe2, 0xaf, 0x02, 0xe0, 0x1b, 0xf0, 0x7b, 0x00, 0xd6, 0xde, - 0xef, 0x65, 0x80, 0xae, 0xae, 0xfd, 0x32, 0x80, 0xa9, 0x7c, 0xd8, 0x7e, - 0x7c, 0x08, 0xe8, 0xcf, 0xbf, 0x97, 0x01, 0xfd, 0xbd, 0x78, 0x9e, 0x07, - 0xfc, 0x7b, 0x00, 0x3e, 0x19, 0xff, 0x31, 0xe0, 0xf3, 0x8d, 0xfe, 0xc5, - 0x38, 0xdc, 0x8f, 0xf4, 0x6d, 0x2e, 0xdd, 0x66, 0xeb, 0xef, 0x99, 0xd3, - 0x73, 0x36, 0xf6, 0x32, 0x60, 0xce, 0x93, 0x5e, 0x07, 0xac, 0xd3, 0x9f, - 0x97, 0xfb, 0xc3, 0x9c, 0x6b, 0xdc, 0x00, 0xf4, 0x97, 0xe2, 0x0d, 0x40, - 0x9f, 0x59, 0xde, 0x01, 0x88, 0xe1, 0x5d, 0x37, 0xfd, 0x29, 0xe0, 0x7b, - 0x7c, 0x8f, 0xaf, 0x19, 0x77, 0x3f, 0xb6, 0xf6, 0x3f, 0x15, 0x5e, 0x1c, - 0xca, 0x9b, 0x04, 0x27, 0x70, 0xeb, 0xc0, 0x63, 0x8e, 0x1d, 0x3e, 0x0f, - 0xb0, 0x56, 0xfe, 0x99, 0x77, 0x00, 0x7f, 0xdc, 0x05, 0xfc, 0xf5, 0xe9, - 0x12, 0x6e, 0x01, 0x3e, 0xdf, 0xad, 0xb7, 0x23, 0x7d, 0x9f, 0x4b, 0xb7, - 0xd9, 0x7a, 0x3f, 0x1f, 0xbe, 0xc7, 0xff, 0x75, 0xfc, 0x0d, 0x3b, 0xd4, - 0xd5, 0x4b, 0x3b, 0xfe, 0xb6, 0x75, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, - 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 -}; - -const u32 TEXTURE_ATLAS_LENGTH = (u32)std::size(TEXTURE_ATLAS); -const vec2 TEXTURE_ATLAS_SIZE = {96, 160}; - -enum AtlasType -{ - ATLAS_NONE, - ATLAS_FOLDER, - ATLAS_ROOT, - ATLAS_LAYER, - ATLAS_NULL, - ATLAS_TRIGGERS, - ATLAS_VISIBLE, - ATLAS_INVISIBLE, - ATLAS_SHOW_RECT, - ATLAS_HIDE_RECT, - ATLAS_SHOW_UNUSED, - ATLAS_HIDE_UNUSED, - ATLAS_PAN, - ATLAS_MOVE, - ATLAS_ROTATE, - ATLAS_SCALE, - ATLAS_CROP, - ATLAS_DRAW, - ATLAS_ERASE, - ATLAS_COLOR_PICKER, - ATLAS_UNDO, - ATLAS_REDO, - ATLAS_ANIMATION, - ATLAS_SPRITESHEET, - ATLAS_EVENT, - ATLAS_PLAY, - ATLAS_PAUSE, - ATLAS_ADD, - ATLAS_REMOVE, - ATLAS_TRIGGER, - ATLAS_PIVOT, - ATLAS_SQUARE, - ATLAS_CIRCLE, - ATLAS_PICKER, - ATLAS_FRAME, - ATLAS_FRAME_ALT, - ATLAS_TARGET, - ATLAS_TARGET_ALT, - ATLAS_COUNT -}; - -struct AtlasEntry -{ - vec2 position; - vec2 size; -}; - -const vec2 ATLAS_SIZE_SMALL = {8, 8}; -const vec2 ATLAS_SIZE_NORMAL = {16, 16}; -const vec2 ATLAS_SIZE_OBLONG = {16, 40}; -const vec2 ATLAS_SIZE_BIG = {40, 40}; - -const inline AtlasEntry ATLAS_ENTRIES[ATLAS_COUNT] = -{ - {{ 0, 0}, ATLAS_SIZE_NORMAL}, - {{ 16, 0}, ATLAS_SIZE_NORMAL}, - {{ 32, 0}, ATLAS_SIZE_NORMAL}, - {{ 48, 0}, ATLAS_SIZE_NORMAL}, - {{ 64, 0}, ATLAS_SIZE_NORMAL}, - {{ 80, 0}, ATLAS_SIZE_NORMAL}, - {{ 0, 16}, ATLAS_SIZE_NORMAL}, - {{ 16, 16}, ATLAS_SIZE_NORMAL}, - {{ 32, 16}, ATLAS_SIZE_NORMAL}, - {{ 48, 16}, ATLAS_SIZE_NORMAL}, - {{ 64, 16}, ATLAS_SIZE_NORMAL}, - {{ 80, 16}, ATLAS_SIZE_NORMAL}, - {{ 0, 32}, ATLAS_SIZE_NORMAL}, - {{ 16, 32}, ATLAS_SIZE_NORMAL}, - {{ 32, 32}, ATLAS_SIZE_NORMAL}, - {{ 48, 32}, ATLAS_SIZE_NORMAL}, - {{ 64, 32}, ATLAS_SIZE_NORMAL}, - {{ 80, 32}, ATLAS_SIZE_NORMAL}, - {{ 0, 48}, ATLAS_SIZE_NORMAL}, - {{ 16, 48}, ATLAS_SIZE_NORMAL}, - {{ 32, 48}, ATLAS_SIZE_NORMAL}, - {{ 48, 48}, ATLAS_SIZE_NORMAL}, - {{ 64, 48}, ATLAS_SIZE_NORMAL}, - {{ 80, 48}, ATLAS_SIZE_NORMAL}, - {{ 0, 64}, ATLAS_SIZE_NORMAL}, - {{ 16, 64}, ATLAS_SIZE_NORMAL}, - {{ 32, 64}, ATLAS_SIZE_NORMAL}, - {{ 48, 64}, ATLAS_SIZE_NORMAL}, - {{ 64, 64}, ATLAS_SIZE_NORMAL}, - {{ 80, 64}, ATLAS_SIZE_SMALL }, - {{ 88, 64}, ATLAS_SIZE_SMALL }, - {{ 80, 72}, ATLAS_SIZE_SMALL }, - {{ 88, 72}, ATLAS_SIZE_SMALL }, - {{ 0, 80}, ATLAS_SIZE_OBLONG}, - {{16, 80}, ATLAS_SIZE_OBLONG}, - {{32, 80}, ATLAS_SIZE_OBLONG}, - {{48, 80}, ATLAS_SIZE_BIG}, - {{48, 120}, ATLAS_SIZE_BIG} -}; - -#define ATLAS_POSITION(type) ATLAS_ENTRIES[type].position -#define ATLAS_SIZE(type) ATLAS_ENTRIES[type].size -#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) -#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) - -struct ShaderData -{ - std::string vertex; - std::string fragment; -}; - -enum ShaderType -{ - SHADER_LINE, - SHADER_TEXTURE, - SHADER_AXIS, - SHADER_GRID, - SHADER_COUNT -}; - -const std::string SHADER_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; -layout (location = 1) in vec2 i_uv; -out vec2 i_uv_out; -uniform mat4 u_transform; -void main() -{ - i_uv_out = i_uv; - gl_Position = u_transform * vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_AXIS_VERTEX = R"( -#version 330 core -layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 -uniform vec2 u_origin_ndc; // world origin in NDC -uniform int u_axis; // 0 = X axis, 1 = Y axis - -void main() -{ - vec2 pos = (u_axis == 0) - ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen - : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; - - gl_Position = vec4(pos, 0.0, 1.0); -} -)"; - -const std::string SHADER_GRID_VERTEX = R"( -#version 330 core -layout ( location = 0 ) in vec2 i_position; -out vec2 clip; - -void main() { - clip = i_position; - gl_Position = vec4(i_position, 0.0, 1.0); -} -)"; - -const std::string SHADER_FRAGMENT = R"( -#version 330 core -out vec4 o_fragColor; -uniform vec4 u_color; -void main() -{ - o_fragColor = u_color; -} -)"; - -const std::string SHADER_TEXTURE_FRAGMENT = R"( -#version 330 core -in vec2 i_uv_out; -uniform sampler2D u_texture; -uniform vec4 u_tint; -uniform vec3 u_color_offset; -out vec4 o_fragColor; -void main() -{ - vec4 texColor = texture(u_texture, i_uv_out); - texColor *= u_tint; - texColor.rgb += u_color_offset; - o_fragColor = texColor; -} -)"; - -const std::string SHADER_GRID_FRAGMENT = R"( -#version 330 core -in vec2 clip; - -uniform mat4 u_model; -uniform vec2 u_size; -uniform vec2 u_offset; -uniform vec4 u_color; - -out vec4 o_fragColor; - -void main() -{ - vec4 w = u_model * vec4(clip, 0.0, 1.0); - w /= w.w; - vec2 world = w.xy; - - vec2 g = (world - u_offset) / u_size; - - vec2 d = abs(fract(g) - 0.5); - float distance = min(d.x, d.y); - - float fw = min(fwidth(g.x), fwidth(g.y)); - float alpha = 1.0 - smoothstep(0.0, fw, distance); - - if (alpha <= 0.0) discard; - o_fragColor = vec4(u_color.rgb, u_color.a * alpha); -} -)"; - -#define SHADER_UNIFORM_AXIS "u_axis" -#define SHADER_UNIFORM_COLOR "u_color" -#define SHADER_UNIFORM_TRANSFORM "u_transform" -#define SHADER_UNIFORM_TINT "u_tint" -#define SHADER_UNIFORM_COLOR_OFFSET "u_color_offset" -#define SHADER_UNIFORM_OFFSET "u_offset" -#define SHADER_UNIFORM_ORIGIN_NDC "u_origin_ndc" -#define SHADER_UNIFORM_SIZE "u_size" -#define SHADER_UNIFORM_MODEL "u_model" -#define SHADER_UNIFORM_TEXTURE "u_texture" - -const ShaderData SHADER_DATA[SHADER_COUNT] = -{ - {SHADER_VERTEX, SHADER_FRAGMENT}, - {SHADER_VERTEX, SHADER_TEXTURE_FRAGMENT}, - {SHADER_AXIS_VERTEX, SHADER_FRAGMENT}, - {SHADER_GRID_VERTEX, SHADER_GRID_FRAGMENT} -}; diff --git a/src/anm2.cpp b/src/anm2.cpp deleted file mode 100644 index c65d2ec..0000000 --- a/src/anm2.cpp +++ /dev/null @@ -1,1346 +0,0 @@ -#include "anm2.h" - -using namespace tinyxml2; - -static void _anm2_created_on_set(Anm2* self) -{ - auto now = std::chrono::system_clock::now(); - std::time_t time = std::chrono::system_clock::to_time_t(now); - std::tm localTime = *std::localtime(&time); - - std::ostringstream timeString; - timeString << std::put_time(&localTime, ANM2_CREATED_ON_FORMAT); - self->createdOn = timeString.str(); -} - -static void _anm2_frame_serialize(Anm2Frame* frame, Anm2Type type, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, std::string* string = nullptr) -{ - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); - - if (type == ANM2_TRIGGERS) - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame->eventID); // EventID - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame->atFrame); // AtFrame - } - else - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_POSITION], frame->position.x); // XPosition - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_POSITION], frame->position.y); // YPosition - - if (type == ANM2_LAYER) - { - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_PIVOT], frame->pivot.x); // XPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_PIVOT], frame->pivot.y); // YPivot - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_CROP], frame->crop.x); // XCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_CROP], frame->crop.y); // YCrop - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_WIDTH], frame->size.x); // Width - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_HEIGHT], frame->size.y); // Height - } - - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_X_SCALE], frame->scale.x); // XScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_Y_SCALE], frame->scale.y); // YScale - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DELAY], frame->delay); /* Delay */ - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], frame->isVisible); // Visible - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_TINT], FLOAT_TO_U8(frame->tintRGBA.r)); // RedTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_TINT], FLOAT_TO_U8(frame->tintRGBA.g)); // GreenTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_TINT], FLOAT_TO_U8(frame->tintRGBA.b)); // BlueTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ALPHA_TINT], FLOAT_TO_U8(frame->tintRGBA.a)); // AlphaTint - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_RED_OFFSET], FLOAT_TO_U8(frame->offsetRGB.r)); // RedOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_GREEN_OFFSET], FLOAT_TO_U8(frame->offsetRGB.g)); // GreenOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_BLUE_OFFSET], FLOAT_TO_U8(frame->offsetRGB.b)); // BlueOffset - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ROTATION], frame->rotation); // Rotation - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_INTERPOLATED], frame->isInterpolated); // Interpolated - } - - if (addElement) addElement->InsertEndChild(element); - - if (string && !document) - { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -static void _anm2_animation_serialize(Anm2Animation* animation, XMLDocument* document = nullptr, XMLElement* addElement = nullptr, std::string* string = nullptr) -{ - XMLDocument localDocument; - XMLDocument* useDocument = document ? document : &localDocument; - - // Animation - XMLElement* element = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], animation->name.c_str()); // Name - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FRAME_NUM], animation->frameNum); // FrameNum - element->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LOOP], animation->isLoop); // Loop - - // RootAnimation - XMLElement* rootElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION]); - - for (auto& frame : animation->rootAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_ROOT, useDocument, rootElement); - - element->InsertEndChild(rootElement); - - // LayerAnimations - XMLElement* layersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS]); - - for (auto& id : animation->layerOrder) - { - // LayerAnimation - Anm2Item& layerAnimation = animation->layerAnimations[id]; - XMLElement* layerElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_LAYER_ID], id); // LayerId - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], layerAnimation.isVisible); // Visible - - for (auto& frame : layerAnimation.frames) - _anm2_frame_serialize(&frame, ANM2_LAYER, useDocument, layerElement); - - layersElement->InsertEndChild(layerElement); - } - - element->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS]); - - for (auto& [id, null] : animation->nullAnimations) - { - // NullAnimation - XMLElement* nullElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NULL_ID], id); // NullId - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VISIBLE], null.isVisible); // Visible - - for (auto& frame : null.frames) - _anm2_frame_serialize(&frame, ANM2_NULL, useDocument, nullElement); - - nullsElement->InsertEndChild(nullElement); - } - - element->InsertEndChild(nullsElement); - - // Triggers - XMLElement* triggersElement = useDocument->NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]); - - for (auto& frame : animation->triggers.frames) - _anm2_frame_serialize(&frame, ANM2_TRIGGERS, useDocument, triggersElement); - - element->InsertEndChild(triggersElement); - - if (addElement) addElement->InsertEndChild(element); - - if (string && !document) - { - useDocument->InsertEndChild(element); - XMLPrinter printer; - useDocument->Print(&printer); - *string = std::string(printer.CStr()); - } -} - -bool anm2_serialize(Anm2* self, const std::string& path) -{ - XMLDocument document; - - if (!self || path.empty()) return false; - - if (self->version == 0) _anm2_created_on_set(self); - - self->path = path; - self->version++; - - // AnimatedActor - XMLElement* animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]); - document.InsertFirstChild(animatedActorElement); - - // Info - XMLElement* infoElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO]); - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_BY], self->createdBy.c_str()); // CreatedBy - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_CREATED_ON], self->createdOn.c_str()); // CreatedOn - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_VERSION], self->version); // Version - infoElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_FPS], self->fps); // FPS - animatedActorElement->InsertEndChild(infoElement); - - // Content - XMLElement* contentElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT]); - - // Spritesheets - XMLElement* spritesheetsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS]); - - for (auto& [id, spritesheet] : self->spritesheets) - { - // Spritesheet - XMLElement* spritesheetElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_PATH], spritesheet.path.c_str()); // Path - spritesheetElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - spritesheetsElement->InsertEndChild(spritesheetElement); - } - - contentElement->InsertEndChild(spritesheetsElement); - - // Layers - XMLElement* layersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS]); - - for (auto& [id, layer] : self->layers) - { - // Layer - XMLElement* layerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], layer.name.c_str()); // Path - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - layerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SPRITESHEET_ID], layer.spritesheetID); // SpritesheetId - layersElement->InsertEndChild(layerElement); - } - - contentElement->InsertEndChild(layersElement); - - // Nulls - XMLElement* nullsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS]); - - for (auto& [id, null] : self->nulls) - { - // Null - XMLElement* nullElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], null.name.c_str()); // Name - nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - if (null.isShowRect) nullElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_SHOW_RECT], null.isShowRect); // ShowRect - nullsElement->InsertEndChild(nullElement); - } - - contentElement->InsertEndChild(nullsElement); - - // Events - XMLElement* eventsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS]); - - for (auto& [id, event] : self->events) - { - // Event - XMLElement* eventElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_NAME], event.name.c_str()); // Name - eventElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_ID], id); // ID - eventsElement->InsertEndChild(eventElement); - } - - contentElement->InsertEndChild(eventsElement); - - animatedActorElement->InsertEndChild(contentElement); - - // Animations - XMLElement* animationsElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS]); - if (self->defaultAnimationID != ID_NONE) - animationsElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_DEFAULT_ANIMATION], self->animations[self->defaultAnimationID].name.c_str()); // DefaultAnimation - - for (auto& [id, animation] : self->animations) - _anm2_animation_serialize(&animation, &document, animationsElement); - - animatedActorElement->InsertEndChild(animationsElement); - - XMLError error = document.SaveFile(path.c_str()); - - if (error != XML_SUCCESS) - { - log_error(std::format(ANM2_WRITE_ERROR, path)); - return false; - } - - log_info(std::format(ANM2_WRITE_INFO, path)); - - return true; -} - -static void _anm2_frame_deserialize(Anm2Frame* frame, const XMLElement* element) -{ - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_X_POSITION: frame->position.x = std::atof(attribute->Value()); break; // XPosition - case ANM2_ATTRIBUTE_Y_POSITION: frame->position.y = std::atof(attribute->Value()); break; // YPosition - case ANM2_ATTRIBUTE_X_PIVOT: frame->pivot.x = std::atof(attribute->Value()); break; // XPivot - case ANM2_ATTRIBUTE_Y_PIVOT: frame->pivot.y = std::atof(attribute->Value()); break; // YPivot - case ANM2_ATTRIBUTE_X_CROP: frame->crop.x = std::atof(attribute->Value()); break; // XCrop - case ANM2_ATTRIBUTE_Y_CROP: frame->crop.y = std::atof(attribute->Value()); break; // YCrop - case ANM2_ATTRIBUTE_WIDTH: frame->size.x = std::atof(attribute->Value()); break; // Width - case ANM2_ATTRIBUTE_HEIGHT: frame->size.y = std::atof(attribute->Value()); break; // Height - case ANM2_ATTRIBUTE_X_SCALE: frame->scale.x = std::atof(attribute->Value()); break; // XScale - case ANM2_ATTRIBUTE_Y_SCALE: frame->scale.y = std::atof(attribute->Value()); break; // YScale - case ANM2_ATTRIBUTE_RED_TINT: frame->tintRGBA.r = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // RedTint - case ANM2_ATTRIBUTE_GREEN_TINT: frame->tintRGBA.g = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // GreenTint - case ANM2_ATTRIBUTE_BLUE_TINT: frame->tintRGBA.b = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // BlueTint - case ANM2_ATTRIBUTE_ALPHA_TINT: frame->tintRGBA.a = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // AlphaTint - case ANM2_ATTRIBUTE_RED_OFFSET: frame->offsetRGB.r = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // RedOffset - case ANM2_ATTRIBUTE_GREEN_OFFSET: frame->offsetRGB.g = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // GreenOffset - case ANM2_ATTRIBUTE_BLUE_OFFSET: frame->offsetRGB.b = U8_TO_FLOAT(std::atoi(attribute->Value())); break; // BlueOffset - case ANM2_ATTRIBUTE_ROTATION: frame->rotation = std::atof(attribute->Value()); break; // Rotation - case ANM2_ATTRIBUTE_VISIBLE: frame->isVisible = string_to_bool(attribute->Value()); break; // Visible - case ANM2_ATTRIBUTE_INTERPOLATED: frame->isInterpolated = string_to_bool(attribute->Value()); break; // Interpolated - case ANM2_ATTRIBUTE_AT_FRAME: frame->atFrame = std::atoi(attribute->Value()); break; // AtFrame - case ANM2_ATTRIBUTE_DELAY: frame->delay = std::atoi(attribute->Value()); break; // Delay - case ANM2_ATTRIBUTE_EVENT_ID: frame->eventID = std::atoi(attribute->Value()); break; // EventID - default: break; - } - } -} - -static void _anm2_animation_deserialize(Anm2Animation* animation, const XMLElement* element) -{ - auto frames_deserialize = [&](const XMLElement* itemElement, Anm2Item* item) - { - // Frame - for - ( - const XMLElement* frame = itemElement->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]); - frame; frame = frame->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) - ) - _anm2_frame_deserialize(&item->frames.emplace_back(Anm2Frame()), frame); - }; - - s32 id{}; - - for (const XMLAttribute* attribute = element->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: animation->name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_FRAME_NUM: animation->frameNum = std::atoi(attribute->Value()); break; // FrameNum - case ANM2_ATTRIBUTE_LOOP: animation->isLoop = string_to_bool(attribute->Value()); break; // Loop - default: break; - } - } - - // RootAnimation - if (const XMLElement* rootAnimation = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ROOT_ANIMATION])) - frames_deserialize(rootAnimation, &animation->rootAnimation); - - // LayerAnimations - if (const XMLElement* layerAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATIONS])) - { - // LayerAnimation - for - ( - const XMLElement* layerAnimation = layerAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]); - layerAnimation; layerAnimation = layerAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER_ANIMATION]) - ) - { - Anm2Item layerAnimationItem; - - for (const XMLAttribute* attribute = layerAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_LAYER_ID: id = std::atoi(attribute->Value()); break; // LayerID - case ANM2_ATTRIBUTE_VISIBLE: layerAnimationItem.isVisible = string_to_bool(attribute->Value()); break; // Visible - default: break; - } - } - - frames_deserialize(layerAnimation, &layerAnimationItem); - animation->layerAnimations[id] = layerAnimationItem; - animation->layerOrder.push_back(id); - } - } - - // NullAnimations - if (const XMLElement* nullAnimations = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATIONS])) - { - // NullAnimation - for - ( - const XMLElement* nullAnimation = nullAnimations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]); - nullAnimation; nullAnimation = nullAnimation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL_ANIMATION]) - ) - { - Anm2Item nullAnimationItem; - - for (const XMLAttribute* attribute = nullAnimation->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NULL_ID: id = std::atoi(attribute->Value()); break; - case ANM2_ATTRIBUTE_VISIBLE: nullAnimationItem.isVisible = string_to_bool(attribute->Value()); break; - default: break; - } - } - - frames_deserialize(nullAnimation, &nullAnimationItem); - animation->nullAnimations[id] = nullAnimationItem; - } - } - - // Triggers - if (const XMLElement* triggers = element->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS])) - { - // Trigger - for - ( - const XMLElement* trigger = triggers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]); - trigger; trigger = trigger->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) - ) - _anm2_frame_deserialize(&animation->triggers.frames.emplace_back(Anm2Frame()), trigger); - } -} - -bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures) -{ - if (!self) return false; - - if (path.empty()) - { - log_error(ANM2_EMPTY_ERROR); - return false; - } - - XMLDocument document; - if (document.LoadFile(path.c_str()) != XML_SUCCESS) - { - log_error(std::format(ANM2_PARSE_ERROR, path, document.ErrorStr())); - return false; - } - - anm2_new(self); - self->path = path; - std::string defaultAnimation{}; - s32 id{}; - - // Save old working directory and then use anm2's path as directory - // (used for loading textures from anm2 correctly which are relative) - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(path); - - const XMLElement* root = document.RootElement(); - - // Info - if (const XMLElement* info = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_INFO])) - { - for (const XMLAttribute* attribute = info->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_CREATED_BY: self->createdBy = std::string(attribute->Value()); break; // CreatedBy - case ANM2_ATTRIBUTE_CREATED_ON: self->createdOn = std::string(attribute->Value()); break; // CreatedOn - case ANM2_ATTRIBUTE_VERSION: self->version = std::atoi(attribute->Value()); break; // Version - case ANM2_ATTRIBUTE_FPS: self->fps = std::atoi(attribute->Value()); break; // FPS - default: break; - } - } - } - - // Content - if (const XMLElement* content = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_CONTENT])) - { - // Spritesheets - if (const XMLElement* spritesheets = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEETS])) - { - for - ( - const XMLElement* spritesheet = spritesheets->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]); - spritesheet; spritesheet = spritesheet->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_SPRITESHEET]) - ) - { - Anm2Spritesheet addSpritesheet; - - for (const XMLAttribute* attribute = spritesheet->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_PATH: - // Spritesheet paths from Isaac Rebirth are made with the assumption that - // the paths are case-insensitive (as the game was developed on Windows) - // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyways) - // If the check doesn't work, set the spritesheet path to lowercase - // If the check doesn't work, replace backslashes with slashes - // At the minimum this should make all textures be able to be loaded on Linux - // If it doesn't work beyond that then that's on the user :^) - addSpritesheet.path = attribute->Value(); - if (!path_exists(addSpritesheet.path)) addSpritesheet.path = string_to_lowercase(addSpritesheet.path); - if (!path_exists(addSpritesheet.path)) addSpritesheet.path = string_backslash_replace(addSpritesheet.path); - if (isTextures) texture_from_path_init(&addSpritesheet.texture, addSpritesheet.path); - break; - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; - default: break; - } - } - - self->spritesheets[id] = addSpritesheet; - } - } - - // Layers - if (const XMLElement* layers = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYERS])) - { - for - ( - const XMLElement* layer = layers->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]); - layer; layer = layer->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_LAYER]) - ) - { - Anm2Layer addLayer; - - for (const XMLAttribute* attribute = layer->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addLayer.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // ID - case ANM2_ATTRIBUTE_SPRITESHEET_ID: addLayer.spritesheetID = std::atoi(attribute->Value()); break; // ID - default: break; - } - } - - self->layers[id] = addLayer; - } - } - - // Nulls - if (const XMLElement* nulls = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULLS])) - { - for - ( - const XMLElement* null = nulls->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]); - null; null = null->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_NULL]) - ) - { - Anm2Null addNull; - - for (const XMLAttribute* attribute = null->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addNull.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // IDs - default: break; - } - } - - self->nulls[id] = addNull; - } - } - - // Events - if (const XMLElement* events = content->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENTS])) - { - // Event - for - ( - const XMLElement* event = events->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]); - event; event = event->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_EVENT]) - ) - { - Anm2Event addEvent; - - for (const XMLAttribute* attribute = event->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_NAME: addEvent.name = std::string(attribute->Value()); break; // Name - case ANM2_ATTRIBUTE_ID: id = std::atoi(attribute->Value()); break; // ID - default: break; - } - } - - self->events[id] = addEvent; - } - } - } - - // Animations - if (const XMLElement* animations = root->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATIONS])) - { - for (const XMLAttribute* attribute = animations->FirstAttribute(); attribute; attribute = attribute->Next()) - { - switch (ANM2_ATTRIBUTE_STRING_TO_ENUM(attribute->Name())) - { - case ANM2_ATTRIBUTE_DEFAULT_ANIMATION: defaultAnimation = std::string(attribute->Value()); break; // DefaultAnimation - default: break; - } - } - - // Animation - for - ( - const XMLElement* animation = animations->FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]); - animation; animation = animation->NextSiblingElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION]) - ) - _anm2_animation_deserialize(&self->animations[map_next_id_get(self->animations)], animation); - } - - for (auto& [id, animation] : self->animations) - if (animation.name == defaultAnimation) - self->defaultAnimationID = id; - - if (isTextures) anm2_spritesheet_texture_pixels_download(self); - - std::filesystem::current_path(workingPath); - - log_info(std::format(ANM2_READ_INFO, path)); - - return true; -} - -void anm2_animation_layer_animation_add(Anm2Animation* animation, s32 id) -{ - animation->layerAnimations[id] = Anm2Item{}; - animation->layerOrder.push_back(id); -} - -void anm2_animation_layer_animation_remove(Anm2Animation* animation, s32 id) -{ - animation->layerAnimations.erase(id); - vector_value_erase(animation->layerOrder, id); -} - -void anm2_animation_null_animation_add(Anm2Animation* animation, s32 id) -{ - animation->nullAnimations[id] = Anm2Item{}; -} - -void anm2_animation_null_animation_remove(Anm2Animation* animation, s32 id) -{ - animation->nullAnimations.erase(id); -} - -s32 anm2_layer_add(Anm2* self) -{ - s32 id = map_next_id_get(self->layers); - self->layers[id] = Anm2Layer{}; - return id; -} - -void anm2_layer_remove(Anm2* self, s32 id) -{ - self->layers.erase(id); - - for (auto& [_, animation] : self->animations) - anm2_animation_layer_animation_remove(&animation, id); -} - -s32 anm2_null_add(Anm2* self) -{ - s32 id = map_next_id_get(self->nulls); - self->nulls[id] = Anm2Null{}; - return id; -} - -void anm2_null_remove(Anm2* self, s32 id) -{ - if (!self->nulls.contains(id)) return; - - self->nulls.erase(id); - - for (auto& [_, animation] : self->animations) - anm2_animation_null_animation_remove(&animation, id); -} - -s32 anm2_animation_add(Anm2* self, Anm2Animation* animation, s32 id) -{ - s32 addID = map_next_id_get(self->animations); - - Anm2Animation localAnimation; - Anm2Animation* addAnimation = animation ? animation : &localAnimation; - - if (!animation) addAnimation->rootAnimation.frames.push_back(Anm2Frame{}); - - if (id != ID_NONE) - { - map_insert_shift(self->animations, id, *addAnimation); - return id + 1; - } - else - self->animations[addID] = *addAnimation; - - return addID; -} - -void anm2_animation_remove(Anm2* self, s32 id) -{ - self->animations.erase(id); -} - -void anm2_new(Anm2* self) -{ - *self = Anm2{}; - _anm2_created_on_set(self); -} - -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference* reference) -{ - return map_find(self->animations, reference->animationID); -} - -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference) -{ - if (reference->itemType == ANM2_NONE) return nullptr; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - - if (!animation) return nullptr; - - switch (reference->itemType) - { - case ANM2_ROOT: return &animation->rootAnimation; - case ANM2_LAYER: return map_find(animation->layerAnimations, reference->itemID); - case ANM2_NULL: return map_find(animation->nullAnimations, reference->itemID); - case ANM2_TRIGGERS: return &animation->triggers; - default: return nullptr; - } -} - -s32 anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, f32 time) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, &reference); - - if (!animation) return INDEX_NONE; - if (time < 0 || time > animation->frameNum) return INDEX_NONE; - - Anm2Item* item = anm2_item_from_reference(self, &reference); - - if (!item) return INDEX_NONE; - - if (reference.itemType == ANM2_TRIGGERS) - for (auto [i, frame] : std::views::enumerate(item->frames)) - if (frame.atFrame == (s32)time) return i; - - s32 delayCurrent = 0; - s32 delayNext = 0; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - { - delayNext += frame.delay; - - if (time >= delayCurrent && time < delayNext) - return i; - - delayCurrent += frame.delay; - } - - return INDEX_NONE; -} - -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - - if (!item) return nullptr; - - if (reference->frameIndex <= INDEX_NONE || reference->frameIndex >= (s32)item->frames.size()) - return nullptr; - - return &item->frames[reference->frameIndex]; -} - -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32 time) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, &reference); - if (!animation) return; - - time = std::clamp(ROUND_NEAREST_MULTIPLE(time, 1.0f), 0.0f, animation->frameNum - 1.0f); - - Anm2Item* item = anm2_item_from_reference(self, &reference); - - if (!item) return; - - Anm2Frame* frameNext = nullptr; - s32 delayCurrent = 0; - s32 delayNext = 0; - - for (auto [i, iFrame] : std::views::enumerate(item->frames)) - { - if (reference.itemType == ANM2_TRIGGERS) - { - if ((s32)time == iFrame.atFrame) - { - *frame = iFrame; - break; - } - } - else - { - *frame = iFrame; - - delayNext += frame->delay; - - if (time >= delayCurrent && time < delayNext) - { - if (i + 1 < (s32)item->frames.size()) - frameNext = &item->frames[i + 1]; - else - frameNext = nullptr; - break; - } - - delayCurrent += frame->delay; - } - } - - if (reference.itemType == ANM2_TRIGGERS) - return; - - if (frame->isInterpolated && frameNext && frame->delay > 1) - { - f32 interpolation = (time - delayCurrent) / (delayNext - delayCurrent); - - frame->rotation = glm::mix(frame->rotation, frameNext->rotation, interpolation); - frame->position = glm::mix(frame->position, frameNext->position, interpolation); - frame->scale = glm::mix(frame->scale, frameNext->scale, interpolation); - frame->offsetRGB = glm::mix(frame->offsetRGB, frameNext->offsetRGB, interpolation); - frame->tintRGBA = glm::mix(frame->tintRGBA, frameNext->tintRGBA, interpolation); - } -} - -s32 anm2_animation_length_get(Anm2Animation* self) -{ - s32 length = 0; - - auto accumulate_max_delay = [&](const std::vector& frames) - { - s32 delaySum = 0; - for (const auto& frame : frames) - { - delaySum += frame.delay; - length = std::max(length, delaySum); - } - }; - - accumulate_max_delay(self->rootAnimation.frames); - - for (const auto& [_, item] : self->layerAnimations) - accumulate_max_delay(item.frames); - - for (const auto& [_, item] : self->nullAnimations) - accumulate_max_delay(item.frames); - - for (const auto& frame : self->triggers.frames) - length = std::max(length, frame.atFrame + 1); - - return length; -} - -void anm2_animation_length_set(Anm2Animation* self) -{ - self->frameNum = anm2_animation_length_get(self); -} - -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference* reference) -{ - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!animation || !item) return nullptr; - - Anm2Frame frameAdd = frame ? *frame : Anm2Frame{}; - - if (reference->itemType == ANM2_TRIGGERS) - { - s32 atFrame = reference->time != VALUE_NONE ? (s32)reference->time : 0; - - for (auto& frameCheck : item->frames) - { - if (frameCheck.atFrame == atFrame) - { - atFrame++; - break; - } - } - - frameAdd.delay = 1; - frameAdd.atFrame = atFrame; - return &item->frames.emplace_back(frameAdd); - } - else - { - s32 index = reference->frameIndex; - - if (index < 0 || index >= (s32)item->frames.size()) - { - item->frames.push_back(frameAdd); - return &item->frames.back(); - } - else - { - item->frames.insert(item->frames.begin() + index, frameAdd); - return &item->frames[(size_t)(index)]; - } - } -} - -void anm2_frame_remove(Anm2* self, Anm2Reference* reference) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - item->frames.erase(item->frames.begin() + reference->frameIndex); -} - -void anm2_reference_clear(Anm2Reference* self) -{ - *self = Anm2Reference{}; -} - -void anm2_reference_item_clear(Anm2Reference* self) -{ - *self = {self->animationID}; -} - -void anm2_reference_frame_clear(Anm2Reference* self) -{ - self->frameIndex = INDEX_NONE; -} - -void anm2_item_frame_set(Anm2* self, Anm2Reference* reference, const Anm2FrameChange& change, Anm2ChangeType type, s32 start, s32 count) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - if (start < 0 || count <= 0) return; - const s32 size = (s32)item->frames.size(); - if (size == 0 || start >= size) return; - - const s32 end = std::min(start + count, size); - - for (s32 i = start; i < end; ++i) - { - Anm2Frame& dest = item->frames[i]; - - // Booleans always just set if provided - if (change.isVisible) dest.isVisible = *change.isVisible; - if (change.isInterpolated) dest.isInterpolated = *change.isInterpolated; - - switch (type) - { - case ANM2_CHANGE_SET: - if (change.rotation) dest.rotation = *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, *change.delay); - if (change.crop) dest.crop = *change.crop; - if (change.pivot) dest.pivot = *change.pivot; - if (change.position) dest.position = *change.position; - if (change.size) dest.size = *change.size; - if (change.scale) dest.scale = *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(*change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(*change.tintRGBA, 0.0f, 1.0f); - break; - - case ANM2_CHANGE_ADD: - if (change.rotation) dest.rotation += *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, dest.delay + *change.delay); - if (change.crop) dest.crop += *change.crop; - if (change.pivot) dest.pivot += *change.pivot; - if (change.position) dest.position += *change.position; - if (change.size) dest.size += *change.size; - if (change.scale) dest.scale += *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(dest.offsetRGB + *change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(dest.tintRGBA + *change.tintRGBA, 0.0f, 1.0f); - break; - - case ANM2_CHANGE_SUBTRACT: - if (change.rotation) dest.rotation -= *change.rotation; - if (change.delay) dest.delay = std::max(ANM2_FRAME_DELAY_MIN, dest.delay - *change.delay); - if (change.crop) dest.crop -= *change.crop; - if (change.pivot) dest.pivot -= *change.pivot; - if (change.position) dest.position -= *change.position; - if (change.size) dest.size -= *change.size; - if (change.scale) dest.scale -= *change.scale; - if (change.offsetRGB) dest.offsetRGB = glm::clamp(dest.offsetRGB - *change.offsetRGB, 0.0f, 1.0f); - if (change.tintRGBA) dest.tintRGBA = glm::clamp(dest.tintRGBA - *change.tintRGBA, 0.0f, 1.0f); - break; - } - } -} - -void anm2_animation_merge(Anm2* self, s32 animationID, const std::vector& mergeIDs, Anm2MergeType type) -{ - Anm2Animation newAnimation = self->animations[animationID]; - - auto merge_item = [&](Anm2Item& destinationItem, const Anm2Item& sourceItem) - { - switch (type) - { - case ANM2_MERGE_APPEND: - destinationItem.frames.insert(destinationItem.frames.end(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_PREPEND: - destinationItem.frames.insert(destinationItem.frames.begin(), sourceItem.frames.begin(), sourceItem.frames.end()); - break; - case ANM2_MERGE_REPLACE: - if (destinationItem.frames.size() < sourceItem.frames.size()) - destinationItem.frames.resize(sourceItem.frames.size()); - for (s32 i = 0; i < (s32)sourceItem.frames.size(); i++) - destinationItem.frames[i] = sourceItem.frames[i]; - break; - case ANM2_MERGE_IGNORE: - break; - } - }; - - for (auto mergeID : mergeIDs) - { - if (animationID == mergeID) continue; - - const Anm2Animation& mergeAnimation = self->animations[mergeID]; - - merge_item(newAnimation.rootAnimation, mergeAnimation.rootAnimation); - - for (const auto& [id, layerAnimation] : mergeAnimation.layerAnimations) - merge_item(newAnimation.layerAnimations[id], layerAnimation); - - for (const auto& [id, nullAnimation] : mergeAnimation.nullAnimations) - merge_item(newAnimation.nullAnimations[id], nullAnimation); - - merge_item(newAnimation.triggers, mergeAnimation.triggers); - } - - self->animations[animationID] = newAnimation; - - anm2_animation_length_set(&self->animations[animationID]); -} - -void anm2_frame_bake(Anm2* self, Anm2Reference* reference, s32 interval, bool isRoundScale, bool isRoundRotation) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - Anm2Frame* frame = anm2_frame_from_reference(self, reference); - if (!frame) return; - - Anm2Reference referenceNext = *reference; - referenceNext.frameIndex = reference->frameIndex + 1; - - Anm2Frame* frameNext = anm2_frame_from_reference(self, &referenceNext); - if (!frameNext) frameNext = frame; - - const Anm2Frame baseFrame = *frame; - const Anm2Frame baseFrameNext = *frameNext; - - s32 delay = 0; - s32 insertIndex = reference->frameIndex; - - while (delay < baseFrame.delay) - { - f32 interpolation = (f32)delay / baseFrame.delay; - - Anm2Frame baked = *frame; - baked.delay = std::min(interval, baseFrame.delay - delay); - baked.isInterpolated = (insertIndex == reference->frameIndex) ? baseFrame.isInterpolated : false; - - baked.rotation = glm::mix(baseFrame.rotation, baseFrameNext.rotation, interpolation); - baked.position = glm::mix(baseFrame.position, baseFrameNext.position, interpolation); - baked.scale = glm::mix(baseFrame.scale, baseFrameNext.scale, interpolation); - baked.offsetRGB = glm::mix(baseFrame.offsetRGB, baseFrameNext.offsetRGB, interpolation); - baked.tintRGBA = glm::mix(baseFrame.tintRGBA, baseFrameNext.tintRGBA, interpolation); - - if (isRoundScale) baked.scale = vec2((s32)baked.scale.x, (s32)baked.scale.y); - if (isRoundRotation) baked.rotation = (s32)baked.rotation; - - if (insertIndex == reference->frameIndex) - item->frames[insertIndex] = baked; - else - item->frames.insert(item->frames.begin() + insertIndex, baked); - insertIndex++; - - delay += baked.delay; - } -} - -void anm2_scale(Anm2* self, f32 scale) -{ - auto frame_scale = [&](Anm2Frame& frame) - { - frame.position = vec2((s32)(frame.position.x * scale), (s32)(frame.position.y * scale)); - frame.size = vec2((s32)(frame.size.x * scale), (s32)(frame.size.y * scale)); - frame.crop = vec2((s32)(frame.crop.x * scale), (s32)(frame.crop.y * scale)); - frame.pivot = vec2((s32)(frame.pivot.x * scale), (s32)(frame.pivot.y * scale)); - }; - - for (auto& [_, animation] : self->animations) - { - for (auto& frame : animation.rootAnimation.frames) - frame_scale(frame); - - for (auto& [_, layerAnimation] : animation.layerAnimations) - for (auto& frame : layerAnimation.frames) - frame_scale(frame); - - for (auto& [_, nullAnimation] : animation.nullAnimations) - for (auto& frame : nullAnimation.frames) - frame_scale(frame); - } -} - -void anm2_generate_from_grid(Anm2* self, Anm2Reference* reference, vec2 startPosition, vec2 size, vec2 pivot, s32 columns, s32 count, s32 delay) -{ - Anm2Item* item = anm2_item_from_reference(self, reference); - if (!item) return; - - Anm2Reference frameReference = *reference; - - for (s32 i = 0; i < count; i++) - { - const s32 row = i / columns; - const s32 column = i % columns; - - Anm2Frame frame{}; - - frame.delay = delay; - frame.pivot = pivot; - frame.size = size; - frame.crop = startPosition + vec2(size.x * column, size.y * row); - - anm2_frame_add(self, &frame, &frameReference); - frameReference.frameIndex++; - } -} - -void anm2_free(Anm2* self) -{ - for (auto& [id, spritesheet] : self->spritesheets) - texture_free(&spritesheet.texture); -} - -void anm2_spritesheet_texture_pixels_upload(Anm2* self) -{ - for (auto& [_, spritesheet] : self->spritesheets) - { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) - { - assert(!spritesheet.pixels.empty()); - glBindTexture(GL_TEXTURE_2D, texture.id); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture.size.x, texture.size.y, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -void anm2_spritesheet_texture_pixels_download(Anm2* self) -{ - for (auto& [_, spritesheet] : self->spritesheets) - { - Texture& texture = spritesheet.texture; - - if (texture.id != GL_ID_NONE && !texture.isInvalid) - { - size_t bufferSize = (size_t)texture.size.x * (size_t)texture.size.y * TEXTURE_CHANNELS; - spritesheet.pixels.resize(bufferSize); - glBindTexture(GL_TEXTURE_2D, texture.id); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, spritesheet.pixels.data()); - } - } -} - -vec4 anm2_animation_rect_get(Anm2* self, Anm2Reference* reference, bool isRootTransform) -{ - f32 minX = std::numeric_limits::infinity(); - f32 minY = std::numeric_limits::infinity(); - f32 maxX = -std::numeric_limits::infinity(); - f32 maxY = -std::numeric_limits::infinity(); - - bool any = false; - - Anm2Frame frame; - Anm2Frame root; - - Anm2Animation* animation = anm2_animation_from_reference(self, reference); - if (!animation) return vec4(-1.0f); - - for (f32 t = 0.0f; t <= animation->frameNum; t += 1.0f) - { - for (const auto& [id, _] : animation->layerAnimations) - { - anm2_frame_from_time(self, &frame, {reference->animationID, ANM2_LAYER, id}, t); - if (!frame.isVisible) continue; - if (frame.size.x <= 0 || frame.size.y <= 0) continue; - - mat4 rootModel(1.0f); - if (isRootTransform) - { - anm2_frame_from_time(self, &root, {reference->animationID, ANM2_ROOT}, t); - rootModel = quad_model_parent_get(root.position, root.pivot, PERCENT_TO_UNIT(root.scale), root.rotation); - } - - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 fullModel = rootModel * model; - - vec2 corners[4] = { {0,0}, {1,0}, {1,1}, {0,1} }; - - for (auto& corner : corners) - { - vec4 world = fullModel * vec4(corner, 0.0f, 1.0f); - minX = std::min(minX, world.x); - minY = std::min(minY, world.y); - maxX = std::max(maxX, world.x); - maxY = std::max(maxY, world.y); - any = true; - } - } - } - - if (!any) return vec4(-1.0f); - return {minX, minY, maxX - minX, maxY - minY}; -} - -void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string) -{ - _anm2_animation_serialize(animation, nullptr, nullptr, string); -} - -void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string) -{ - _anm2_frame_serialize(frame, type, nullptr, nullptr, string); -} - -bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml) -{ - XMLDocument document; - - auto animation_deserialize_error = [&]() - { - log_error(std::format(ANM2_ANIMATION_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; - - if (document.Parse(xml.c_str()) != XML_SUCCESS) return animation_deserialize_error(); - - const XMLElement* element = document.RootElement(); - if (!element) return animation_deserialize_error(); - if (std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATION])) - return animation_deserialize_error(); - - _anm2_animation_deserialize(animation, element); - return true; -} - -bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml) -{ - XMLDocument document; - - auto frame_deserialize_error = [&]() - { - log_error(std::format(ANM2_FRAME_PARSE_ERROR, xml, document.ErrorStr())); - return false; - }; - - if (document.Parse(xml.c_str()) != XML_SUCCESS) return frame_deserialize_error(); - - const XMLElement* element = document.RootElement(); - if (!element) return frame_deserialize_error(); - - if - ( - std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_FRAME]) && - std::string(element->Name()) != std::string(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]) - ) - return frame_deserialize_error(); - - _anm2_frame_deserialize(frame, element); - - return true; -} - -/* -void anm2_merge(Anm2* self, const std::string& path, Anm2MergeType type) -{ - Anm2 anm2; - - if (anm2_deserialize(&anm2, path, false)) - { - std::unordered_map spritesheetMap; - for (auto& [id, spritesheet] : anm2.spritesheets) - { - bool isExists = false; - - for (auto& [selfID, selfSpritesheet] : self->spritesheets) - { - if (spritesheet.path == selfSpritesheet.path) isExists = true; - spritesheetMap[id] = selfID; - } - - if (isExists) continue; - - s32 nextID = map_next_id_get(self->spritesheets); - self->spritesheet[nextID] = spritesheet; - spritesheetMap[id] = nextID; - } - - std::unordered_map layerMap; - for (auto& [id, layer] : anm2.layers) - { - bool isExists = false; - - layer.spritesheetID = spritesheetMap[layer.spritesheetID]; - - for (auto& [selfID, selfLayer] : self->layers) - { - if (layer.name == selfLayer.name) isExists = true; - layerMap[id] = selfID; - } - - if (isExists) continue; - - s32 nextID = map_next_id_get(self->layers); - self->layer[nextID] = layer; - layerMap[id] = nextID; - } - - std::unordered_map nullMap; - for (auto& [id, null] : anm2.nulls) - { - bool isExists = false; - - for (auto& [selfID, selfNull] : self->nulls) - { - if (null.name == selfNull.name) isExists = true; - nullMap[id] = selfID; - } - - if (isExists) continue; - - s32 nextID = map_next_id_get(self->nulls); - self->null[nextID] = null; - nullMap[id] = nextID; - } - - std::unordered_map eventMap; - for (auto& [id, event] : anm2.events) - { - bool isExists = false; - - for (auto& [selfID, selfEvent] : self->events) - { - if (event.name == selfEvent.name) isExists = true; - eventMap[id] = selfID; - } - - if (isExists) continue; - - s32 nextID = map_next_id_get(self->events); - self->event[nextID] = event; - eventMap[id] = nextID; - } - - for (auto& [id, animation] : anm2.animations) - { - bool isExists = false; - - for (auto& [selfID, selfAnimation] : self->animations) - { - if (event.name == selfAnimation.name) isExists = true; - eventMap[id] = selfID; - } - - if (isExists) continue; - - for (auto& frame : animation.rootAnimation.frames) - { - - - } - - for (auto& [layerID, layerAnimation] : animation.layerAnimations) - { - s32 newLayerID = layerMap[layerID]; - - - } - } - } -} -*/ \ No newline at end of file diff --git a/src/anm2.h b/src/anm2.h deleted file mode 100644 index 02c8614..0000000 --- a/src/anm2.h +++ /dev/null @@ -1,308 +0,0 @@ -#pragma once - -#include "resources.h" - -#define ANM2_SCALE_CONVERT(x) ((f32)x / 100.0f) -#define ANM2_TINT_CONVERT(x) ((f32)x / 255.0f) - -#define ANM2_FPS_MIN 0 -#define ANM2_FPS_DEFAULT 30 -#define ANM2_FPS_MAX 120 -#define ANM2_FRAME_NUM_MIN 1 -#define ANM2_FRAME_NUM_MAX 1000000 -#define ANM2_FRAME_DELAY_MIN 1 -#define ANM2_STRING_MAX 0xFF - -#define ANM2_EMPTY_ERROR "No path given for anm2" -#define ANM2_READ_ERROR "Failed to read anm2 from file: {}" -#define ANM2_PARSE_ERROR "Failed to parse anm2: {} ({})" -#define ANM2_FRAME_PARSE_ERROR "Failed to parse frame: {} ({})" -#define ANM2_ANIMATION_PARSE_ERROR "Failed to parse frame: {} ({})" -#define ANM2_READ_INFO "Read anm2 from file: {}" -#define ANM2_WRITE_ERROR "Failed to write anm2 to file: {}" -#define ANM2_WRITE_INFO "Wrote anm2 to file: {}" -#define ANM2_CREATED_ON_FORMAT "%d-%B-%Y %I:%M:%S %p" - -#define ANM2_EXTENSION "anm2" -#define ANM2_SPRITESHEET_EXTENSION "png" - -#define ANM2_ELEMENT_LIST \ - X(ANIMATED_ACTOR, "AnimatedActor") \ - X(INFO, "Info") \ - X(CONTENT, "Content") \ - X(SPRITESHEETS, "Spritesheets") \ - X(SPRITESHEET, "Spritesheet") \ - X(LAYERS, "Layers") \ - X(LAYER, "Layer") \ - X(NULLS, "Nulls") \ - X(NULL, "Null") \ - X(EVENTS, "Events") \ - X(EVENT, "Event") \ - X(ANIMATIONS, "Animations") \ - X(ANIMATION, "Animation") \ - X(ROOT_ANIMATION, "RootAnimation") \ - X(FRAME, "Frame") \ - X(LAYER_ANIMATIONS, "LayerAnimations") \ - X(LAYER_ANIMATION, "LayerAnimation") \ - X(NULL_ANIMATIONS, "NullAnimations") \ - X(NULL_ANIMATION, "NullAnimation") \ - X(TRIGGERS, "Triggers") \ - X(TRIGGER, "Trigger") - -typedef enum -{ - #define X(name, str) ANM2_ELEMENT_##name, - ANM2_ELEMENT_LIST - #undef X - ANM2_ELEMENT_COUNT -} Anm2Element; - -const inline char* ANM2_ELEMENT_STRINGS[] = -{ - #define X(name, str) str, - ANM2_ELEMENT_LIST - #undef X -}; - -DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ELEMENT_STRING_TO_ENUM, Anm2Element, ANM2_ELEMENT_STRINGS, ANM2_ELEMENT_COUNT) - -#define ANM2_ATTRIBUTE_LIST \ - X(CREATED_BY, "CreatedBy") \ - X(CREATED_ON, "CreatedOn") \ - X(VERSION, "Version") \ - X(FPS, "Fps") \ - X(ID, "Id") \ - X(PATH, "Path") \ - X(NAME, "Name") \ - X(SPRITESHEET_ID, "SpritesheetId") \ - X(SHOW_RECT, "ShowRect") \ - X(DEFAULT_ANIMATION, "DefaultAnimation") \ - X(FRAME_NUM, "FrameNum") \ - X(LOOP, "Loop") \ - X(X_POSITION, "XPosition") \ - X(Y_POSITION, "YPosition") \ - X(X_PIVOT, "XPivot") \ - X(Y_PIVOT, "YPivot") \ - X(X_CROP, "XCrop") \ - X(Y_CROP, "YCrop") \ - X(WIDTH, "Width") \ - X(HEIGHT, "Height") \ - X(X_SCALE, "XScale") \ - X(Y_SCALE, "YScale") \ - X(DELAY, "Delay") \ - X(VISIBLE, "Visible") \ - X(RED_TINT, "RedTint") \ - X(GREEN_TINT, "GreenTint") \ - X(BLUE_TINT, "BlueTint") \ - X(ALPHA_TINT, "AlphaTint") \ - X(RED_OFFSET, "RedOffset") \ - X(GREEN_OFFSET, "GreenOffset") \ - X(BLUE_OFFSET, "BlueOffset") \ - X(ROTATION, "Rotation") \ - X(INTERPOLATED, "Interpolated") \ - X(LAYER_ID, "LayerId") \ - X(NULL_ID, "NullId") \ - X(EVENT_ID, "EventId") \ - X(AT_FRAME, "AtFrame") - -typedef enum -{ - #define X(name, str) ANM2_ATTRIBUTE_##name, - ANM2_ATTRIBUTE_LIST - #undef X - ANM2_ATTRIBUTE_COUNT -} Anm2Attribute; - -static const char* ANM2_ATTRIBUTE_STRINGS[] = -{ - #define X(name, str) str, - ANM2_ATTRIBUTE_LIST - #undef X -}; - -DEFINE_STRING_TO_ENUM_FUNCTION(ANM2_ATTRIBUTE_STRING_TO_ENUM, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT) - -enum Anm2Type -{ - ANM2_NONE, - ANM2_ROOT, - ANM2_LAYER, - ANM2_NULL, - ANM2_TRIGGERS, - ANM2_COUNT -}; - -struct Anm2Spritesheet -{ - std::string path{}; - Texture texture; - std::vector pixels; - - auto operator<=>(const Anm2Spritesheet&) const = default; -}; - -struct Anm2Layer -{ - std::string name = "New Layer"; - s32 spritesheetID{}; - - auto operator<=>(const Anm2Layer&) const = default; -}; - -struct Anm2Null -{ - std::string name = "New Null"; - bool isShowRect = false; - - auto operator<=>(const Anm2Null&) const = default; -}; - -struct Anm2Event -{ - std::string name = "New Event"; - - auto operator<=>(const Anm2Event&) const = default; -}; - -struct Anm2Frame -{ - bool isVisible = true; - bool isInterpolated = false; - f32 rotation{}; - s32 delay = ANM2_FRAME_DELAY_MIN; - s32 atFrame = INDEX_NONE; - s32 eventID = ID_NONE; - vec2 crop{}; - vec2 pivot{}; - vec2 position{}; - vec2 size{}; - vec2 scale = {100, 100}; - vec3 offsetRGB = COLOR_OFFSET_NONE; - vec4 tintRGBA = COLOR_OPAQUE; - - auto operator<=>(const Anm2Frame&) const = default; -}; - -struct Anm2Item -{ - bool isVisible = true; - std::vector frames; - - auto operator<=>(const Anm2Item&) const = default; -}; - -struct Anm2Animation -{ - s32 frameNum = ANM2_FRAME_NUM_MIN; - std::string name = "New Animation"; - bool isLoop = true; - Anm2Item rootAnimation; - std::unordered_map layerAnimations; - std::vector layerOrder; - std::map nullAnimations; - Anm2Item triggers; - - auto operator<=>(const Anm2Animation&) const = default; -}; - -struct Anm2 -{ - std::string path{}; - std::string createdBy = "robot"; - std::string createdOn{}; - std::map spritesheets; - std::map layers; - std::map nulls; - std::map events; - std::map animations; - s32 defaultAnimationID = ID_NONE; - s32 fps = ANM2_FPS_DEFAULT; - s32 version{}; - - auto operator<=>(const Anm2&) const = default; -}; - -struct Anm2Reference -{ - s32 animationID = ID_NONE; - Anm2Type itemType = ANM2_NONE; - s32 itemID = ID_NONE; - s32 frameIndex = INDEX_NONE; - f32 time = VALUE_NONE; - auto operator<=>(const Anm2Reference&) const = default; -}; - -struct Anm2FrameChange -{ - std::optional isVisible; - std::optional isInterpolated; - std::optional rotation; - std::optional delay; - std::optional crop; - std::optional pivot; - std::optional position; - std::optional size; - std::optional scale; - std::optional offsetRGB; - std::optional tintRGBA; -}; - -enum Anm2MergeType -{ - ANM2_MERGE_APPEND, - ANM2_MERGE_REPLACE, - ANM2_MERGE_PREPEND, - ANM2_MERGE_IGNORE -}; - -enum Anm2ChangeType -{ - ANM2_CHANGE_ADD, - ANM2_CHANGE_SUBTRACT, - ANM2_CHANGE_SET -}; - -enum OnionskinDrawOrder -{ - ONIONSKIN_BELOW, - ONIONSKIN_ABOVE -}; - -Anm2Animation* anm2_animation_from_reference(Anm2* self, Anm2Reference* reference); -Anm2Frame* anm2_frame_add(Anm2* self, Anm2Frame* frame, Anm2Reference* reference); -Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference); -Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference); -bool anm2_animation_deserialize_from_xml(Anm2Animation* animation, const std::string& xml); -bool anm2_deserialize(Anm2* self, const std::string& path, bool isTextures = true); -bool anm2_frame_deserialize_from_xml(Anm2Frame* frame, const std::string& xml); -bool anm2_serialize(Anm2* self, const std::string& path); -s32 anm2_animation_add(Anm2* self, Anm2Animation* animation = nullptr, s32 id = ID_NONE); -s32 anm2_animation_length_get(Anm2Animation* self); -s32 anm2_frame_index_from_time(Anm2* self, Anm2Reference reference, f32 time); -s32 anm2_layer_add(Anm2* self); -s32 anm2_null_add(Anm2* self); -vec4 anm2_animation_rect_get(Anm2* anm2, Anm2Reference* reference, bool isRootTransform); -void anm2_animation_layer_animation_add(Anm2Animation* animation, s32 id); -void anm2_animation_layer_animation_remove(Anm2Animation* animation, s32 id); -void anm2_animation_length_set(Anm2Animation* self); -void anm2_animation_merge(Anm2* self, s32 animationID, const std::vector& mergeIDs, Anm2MergeType type); -void anm2_animation_null_animation_add(Anm2Animation* animation, s32 id); -void anm2_animation_null_animation_remove(Anm2Animation* animation, s32 id); -void anm2_animation_remove(Anm2* self, s32 id); -void anm2_animation_serialize_to_string(Anm2Animation* animation, std::string* string); -void anm2_frame_bake(Anm2* self, Anm2Reference* reference, s32 interval, bool isRoundScale, bool isRoundRotation); -void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, f32 time); -void anm2_frame_remove(Anm2* self, Anm2Reference* reference); -void anm2_frame_serialize_to_string(Anm2Frame* frame, Anm2Type type, std::string* string); -void anm2_free(Anm2* self); -void anm2_generate_from_grid(Anm2* self, Anm2Reference* reference, vec2 startPosition, vec2 size, vec2 pivot, s32 columns, s32 count, s32 delay); -void anm2_item_frame_set(Anm2* self, Anm2Reference* reference, const Anm2FrameChange& change, Anm2ChangeType type, s32 start, s32 count); -void anm2_layer_remove(Anm2* self, s32 id); -void anm2_new(Anm2* self); -void anm2_null_remove(Anm2* self, s32 id); -void anm2_reference_clear(Anm2Reference* self); -void anm2_reference_frame_clear(Anm2Reference* self); -void anm2_reference_item_clear(Anm2Reference* self); -void anm2_scale(Anm2* self, f32 scale); -void anm2_spritesheet_texture_pixels_download(Anm2* self); -void anm2_spritesheet_texture_pixels_upload(Anm2* self); \ No newline at end of file diff --git a/src/anm2/animation.cpp b/src/anm2/animation.cpp new file mode 100644 index 0000000..61d2bb6 --- /dev/null +++ b/src/anm2/animation.cpp @@ -0,0 +1,180 @@ +#include "animation.h" + +#include "map_.h" +#include "math_.h" +#include "unordered_map_.h" +#include "xml_.h" +#include + +using namespace anm2ed::util; +using namespace glm; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Animation::Animation(XMLElement* element) + { + int id{}; + + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("FrameNum", &frameNum); + element->QueryBoolAttribute("Loop", &isLoop); + + if (auto rootAnimationElement = element->FirstChildElement("RootAnimation")) + rootAnimation = Item(rootAnimationElement, ROOT); + + if (auto layerAnimationsElement = element->FirstChildElement("LayerAnimations")) + { + for (auto child = layerAnimationsElement->FirstChildElement("LayerAnimation"); child; + child = child->NextSiblingElement("LayerAnimation")) + { + layerAnimations[id] = Item(child, LAYER, &id); + layerOrder.push_back(id); + } + } + + if (auto nullAnimationsElement = element->FirstChildElement("NullAnimations")) + for (auto child = nullAnimationsElement->FirstChildElement("NullAnimation"); child; + child = child->NextSiblingElement("NullAnimation")) + nullAnimations[id] = Item(child, NULL_, &id); + + if (auto triggersElement = element->FirstChildElement("Triggers")) triggers = Item(triggersElement, TRIGGER); + } + + Item* Animation::item_get(Type type, int id) + { + switch (type) + { + case ROOT: + return &rootAnimation; + case LAYER: + return unordered_map::find(layerAnimations, id); + case NULL_: + return map::find(nullAnimations, id); + case TRIGGER: + return &triggers; + default: + return nullptr; + } + return nullptr; + } + + void Animation::item_remove(Type type, int id) + { + switch (type) + { + case LAYER: + layerAnimations.erase(id); + for (auto [i, value] : std::views::enumerate(layerOrder)) + if (value == id) layerOrder.erase(layerOrder.begin() + i); + break; + case NULL_: + nullAnimations.erase(id); + break; + case ROOT: + case TRIGGER: + default: + break; + } + } + + XMLElement* Animation::to_element(XMLDocument& document) + { + auto element = document.NewElement("Animation"); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("FrameNum", frameNum); + element->SetAttribute("Loop", isLoop); + + rootAnimation.serialize(document, element, ROOT); + + auto layerAnimationsElement = document.NewElement("LayerAnimations"); + for (auto& i : layerOrder) + { + Item& layerAnimation = layerAnimations.at(i); + layerAnimation.serialize(document, layerAnimationsElement, LAYER, i); + } + element->InsertEndChild(layerAnimationsElement); + + auto nullAnimationsElement = document.NewElement("NullAnimations"); + for (auto& [id, nullAnimation] : nullAnimations) + nullAnimation.serialize(document, nullAnimationsElement, NULL_, id); + element->InsertEndChild(nullAnimationsElement); + + triggers.serialize(document, element, TRIGGER); + + return element; + } + + void Animation::serialize(XMLDocument& document, XMLElement* parent) { parent->InsertEndChild(to_element(document)); } + + std::string Animation::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); + } + + int Animation::length() + { + int length{}; + + if (int rootAnimationLength = rootAnimation.length(ROOT); rootAnimationLength > length) + length = rootAnimationLength; + + for (auto& layerAnimation : layerAnimations | std::views::values) + if (int layerAnimationLength = layerAnimation.length(LAYER); layerAnimationLength > length) + length = layerAnimationLength; + + for (auto& nullAnimation : nullAnimations | std::views::values) + if (int nullAnimationLength = nullAnimation.length(NULL_); nullAnimationLength > length) + length = nullAnimationLength; + + if (int triggersLength = triggers.length(TRIGGER); triggersLength > length) length = triggersLength; + + return length; + } + + vec4 Animation::rect(bool isRootTransform) + { + constexpr ivec2 CORNERS[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; + + float minX = std::numeric_limits::infinity(); + float minY = std::numeric_limits::infinity(); + float maxX = -std::numeric_limits::infinity(); + float maxY = -std::numeric_limits::infinity(); + bool any = false; + + for (float t = 0.0f; t < (float)frameNum; t += 1.0f) + { + mat4 transform(1.0f); + + if (isRootTransform) + { + auto root = rootAnimation.frame_generate(t, ROOT); + transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); + } + + for (auto& [id, layerAnimation] : layerAnimations) + { + auto frame = layerAnimation.frame_generate(t, LAYER); + + if (frame.size == vec2() || !frame.isVisible) continue; + + auto layerTransform = transform * math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + for (auto& corner : CORNERS) + { + vec4 world = layerTransform * vec4(corner, 0.0f, 1.0f); + minX = std::min(minX, world.x); + minY = std::min(minY, world.y); + maxX = std::max(maxX, world.x); + maxY = std::max(maxY, world.y); + any = true; + } + } + } + + if (!any) return vec4(-1.0f); + return {minX, minY, maxX - minX, maxY - minY}; + } +} \ No newline at end of file diff --git a/src/anm2/animation.h b/src/anm2/animation.h new file mode 100644 index 0000000..0cc68a8 --- /dev/null +++ b/src/anm2/animation.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "item.h" + +namespace anm2ed::anm2 +{ + constexpr auto FRAME_NUM_MIN = 1; + constexpr auto FRAME_NUM_MAX = FRAME_DELAY_MAX; + + class Animation + { + public: + std::string name{"New Animation"}; + int frameNum{FRAME_NUM_MIN}; + bool isLoop{true}; + Item rootAnimation; + std::unordered_map layerAnimations{}; + std::vector layerOrder{}; + std::map nullAnimations{}; + Item triggers; + + Animation() = default; + Animation(tinyxml2::XMLElement*); + Item* item_get(Type, int = -1); + void item_remove(Type, int = -1); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + std::string to_string(); + int length(); + glm::vec4 rect(bool); + }; + +} \ No newline at end of file diff --git a/src/anm2/animations.cpp b/src/anm2/animations.cpp new file mode 100644 index 0000000..1eaaed4 --- /dev/null +++ b/src/anm2/animations.cpp @@ -0,0 +1,43 @@ +#include "animations.h" + +#include "xml_.h" + +using namespace tinyxml2; +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::anm2 +{ + Animations::Animations(XMLElement* element) + { + xml::query_string_attribute(element, "DefaultAnimation", &defaultAnimation); + + for (auto child = element->FirstChildElement("Animation"); child; child = child->NextSiblingElement("Animation")) + items.push_back(Animation(child)); + } + + XMLElement* Animations::to_element(XMLDocument& document) + { + auto element = document.NewElement("Animations"); + element->SetAttribute("DefaultAnimation", defaultAnimation.c_str()); + for (auto& animation : items) + animation.serialize(document, element); + return element; + } + + void Animations::serialize(XMLDocument& document, XMLElement* parent) + { + parent->InsertEndChild(to_element(document)); + } + + int Animations::length() + { + int length{}; + + for (auto& animation : items) + if (int animationLength = animation.length(); animationLength > length) length = animationLength; + + return length; + } + +} \ No newline at end of file diff --git a/src/anm2/animations.h b/src/anm2/animations.h new file mode 100644 index 0000000..a2c4fe5 --- /dev/null +++ b/src/anm2/animations.h @@ -0,0 +1,20 @@ +#pragma once + +#include "animation.h" + +namespace anm2ed::anm2 +{ + constexpr auto MERGED_STRING = "(Merged)"; + + struct Animations + { + std::string defaultAnimation{}; + std::vector items{}; + + Animations() = default; + Animations(tinyxml2::XMLElement*); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + int length(); + }; +} \ No newline at end of file diff --git a/src/anm2/anm2.cpp b/src/anm2/anm2.cpp new file mode 100644 index 0000000..79963a5 --- /dev/null +++ b/src/anm2/anm2.cpp @@ -0,0 +1,89 @@ +#include "anm2.h" + +#include "filesystem_.h" +#include "time_.h" +#include "vector_.h" +#include "xml_.h" + +using namespace tinyxml2; +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace glm; + +namespace anm2ed::anm2 +{ + Anm2::Anm2() + { + info.createdOn = time::get("%d-%B-%Y %I:%M:%S"); + } + + Anm2::Anm2(const std::string& path, std::string* errorString) + { + XMLDocument document; + + if (document.LoadFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return; + } + + filesystem::WorkingDirectory workingDirectory(path, true); + + const XMLElement* element = document.RootElement(); + + if (auto infoElement = element->FirstChildElement("Info")) info = Info((XMLElement*)infoElement); + if (auto contentElement = element->FirstChildElement("Content")) content = Content((XMLElement*)contentElement); + if (auto animationsElement = element->FirstChildElement("Animations")) + animations = Animations((XMLElement*)animationsElement); + } + + bool Anm2::serialize(const std::string& path, std::string* errorString) + { + XMLDocument document; + + auto* element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + if (document.SaveFile(path.c_str()) != XML_SUCCESS) + { + if (errorString) *errorString = document.ErrorStr(); + return false; + } + return true; + } + + XMLElement* Anm2::to_element(XMLDocument& document) + { + auto element = document.NewElement("AnimatedActor"); + document.InsertFirstChild(element); + + info.serialize(document, element); + content.serialize(document, element); + animations.serialize(document, element); + + return element; + } + + std::string Anm2::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); + } + + uint64_t Anm2::hash() + { + return std::hash{}(to_string()); + } + + Frame* Anm2::frame_get(Reference reference) + { + if (auto item = item_get(reference); item) + if (vector::in_bounds(item->frames, reference.frameIndex)) return &item->frames[reference.frameIndex]; + return nullptr; + } +} \ No newline at end of file diff --git a/src/anm2/anm2.h b/src/anm2/anm2.h new file mode 100644 index 0000000..3f970ff --- /dev/null +++ b/src/anm2/anm2.h @@ -0,0 +1,78 @@ +#pragma once + +#include +#include + +#include "types.h" + +#include "animations.h" +#include "content.h" +#include "info.h" + +namespace anm2ed::anm2 +{ + constexpr auto NO_PATH = "[No Path]"; + + struct Reference + { + int animationIndex{-1}; + Type itemType{NONE}; + int itemID{-1}; + int frameIndex{-1}; + int frameTime{-1}; + + auto operator<=>(const Reference&) const = default; + }; + + class Anm2 + { + public: + Info info{}; + Content content{}; + Animations animations{}; + + Anm2(); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&); + bool serialize(const std::string&, std::string* = nullptr); + std::string to_string(); + Anm2(const std::string&, std::string* = nullptr); + uint64_t hash(); + + Spritesheet* spritesheet_get(int); + bool spritesheet_add(const std::string&, const std::string&, int&); + void spritesheet_remove(int); + std::vector spritesheet_labels_get(); + std::set spritesheets_unused(); + bool spritesheets_deserialize(const std::string&, const std::string&, types::merge::Type type, std::string*); + + void layer_add(int&); + std::set layers_unused(Reference = {}); + bool layers_deserialize(const std::string&, types::merge::Type, std::string*); + + void null_add(int&); + std::set nulls_unused(Reference = {}); + bool nulls_deserialize(const std::string&, types::merge::Type, std::string*); + + void event_add(int&); + std::vector event_labels_get(); + std::set events_unused(Reference = {}); + bool events_deserialize(const std::string&, types::merge::Type, std::string*); + + bool sound_add(const std::string& directory, const std::string& path, int& id); + std::vector sound_labels_get(); + std::set sounds_unused(); + bool sounds_deserialize(const std::string&, const std::string&, types::merge::Type, std::string*); + + Animation* animation_get(Reference); + std::vector animation_labels_get(); + int animations_merge(int, std::set&, types::merge::Type = types::merge::APPEND, bool = true); + bool animations_deserialize(const std::string&, int, std::set&, std::string* = nullptr); + + Item* item_get(Reference); + Reference layer_animation_add(Reference = {}, std::string = {}, int = 0, + types::locale::Type = types::locale::GLOBAL); + Reference null_animation_add(Reference = {}, std::string = {}, types::locale::Type = types::locale::GLOBAL); + + Frame* frame_get(Reference); + }; +} diff --git a/src/anm2/anm2_animations.cpp b/src/anm2/anm2_animations.cpp new file mode 100644 index 0000000..11762d9 --- /dev/null +++ b/src/anm2/anm2_animations.cpp @@ -0,0 +1,139 @@ +#include "anm2.h" + +#include "vector_.h" + +using namespace anm2ed::util; +using namespace anm2ed::types; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Animation* Anm2::animation_get(Reference reference) + { + return vector::find(animations.items, reference.animationIndex); + } + + std::vector Anm2::animation_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& animation : animations.items) + labels.emplace_back(animation.name); + return labels; + } + + bool Anm2::animations_deserialize(const std::string& string, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Animation")) + { + if (errorString) *errorString = "No valid animation(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Animation"); element; + element = element->NextSiblingElement("Animation")) + { + auto index = start + count; + animations.items.insert(animations.items.begin() + start + count, Animation(element)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + int Anm2::animations_merge(int target, std::set& sources, merge::Type type, bool isDeleteAfter) + { + auto& items = animations.items; + auto& animation = animations.items.at(target); + + if (!animation.name.ends_with(MERGED_STRING)) animation.name = animation.name + " " + MERGED_STRING; + + auto merge_item = [&](Item& destination, Item& source) + { + switch (type) + { + case merge::APPEND: + destination.frames.insert(destination.frames.end(), source.frames.begin(), source.frames.end()); + break; + case merge::PREPEND: + destination.frames.insert(destination.frames.begin(), source.frames.begin(), source.frames.end()); + break; + case merge::REPLACE: + if (destination.frames.size() < source.frames.size()) destination.frames.resize(source.frames.size()); + for (int i = 0; i < (int)source.frames.size(); i++) + destination.frames[i] = source.frames[i]; + break; + case merge::IGNORE: + default: + break; + } + }; + + for (auto& i : sources) + { + if (i == target) continue; + if (i < 0 || i >= (int)items.size()) continue; + + auto& source = items.at(i); + + merge_item(animation.rootAnimation, source.rootAnimation); + + for (auto& [id, layerAnimation] : source.layerAnimations) + { + if (!animation.layerAnimations.contains(id)) + { + animation.layerAnimations[id] = layerAnimation; + animation.layerOrder.emplace_back(id); + } + merge_item(animation.layerAnimations[id], layerAnimation); + } + + for (auto& [id, nullAnimation] : source.nullAnimations) + { + if (!animation.nullAnimations.contains(id)) animation.nullAnimations[id] = nullAnimation; + merge_item(animation.nullAnimations[id], nullAnimation); + } + + merge_item(animation.triggers, source.triggers); + } + + if (isDeleteAfter) + { + for (auto& source : std::ranges::reverse_view(sources)) + { + if (source == target) continue; + items.erase(items.begin() + source); + } + } + + int finalIndex = target; + + if (isDeleteAfter) + { + int numDeletedBefore = 0; + for (auto& idx : sources) + { + if (idx == target) continue; + if (idx >= 0 && idx < target) ++numDeletedBefore; + } + finalIndex -= numDeletedBefore; + } + + animation.frameNum = animation.length(); + + return finalIndex; + } + +} \ No newline at end of file diff --git a/src/anm2/anm2_events.cpp b/src/anm2/anm2_events.cpp new file mode 100644 index 0000000..903e6d8 --- /dev/null +++ b/src/anm2/anm2_events.cpp @@ -0,0 +1,75 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::event_add(int& id) + { + id = map::next_id_get(content.events); + content.events[id] = Event(); + } + + std::vector Anm2::event_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& event : content.events | std::views::values) + labels.emplace_back(event.name); + return labels; + } + + std::set Anm2::events_unused(Reference reference) + { + std::set used{}; + + if (auto animation = animation_get(reference); animation) + for (auto& frame : animation->triggers.frames) + used.insert(frame.eventID); + else + for (auto& animation : animations.items) + for (auto& frame : animation.triggers.frames) + used.insert(frame.eventID); + + std::set unused{}; + for (auto& id : content.events | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::events_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Event")) + { + if (errorString) *errorString = "No valid event(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Event"); element; element = element->NextSiblingElement("Event")) + { + auto event = Event(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.events); + content.events[id] = event; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_items.cpp b/src/anm2/anm2_items.cpp new file mode 100644 index 0000000..b74df0e --- /dev/null +++ b/src/anm2/anm2_items.cpp @@ -0,0 +1,83 @@ +#include "anm2.h" + +#include "map_.h" +#include "types.h" +#include "unordered_map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::anm2 +{ + Item* Anm2::item_get(Reference reference) + { + if (Animation* animation = animation_get(reference)) + { + switch (reference.itemType) + { + case ROOT: + return &animation->rootAnimation; + case LAYER: + return unordered_map::find(animation->layerAnimations, reference.itemID); + case NULL_: + return map::find(animation->nullAnimations, reference.itemID); + case TRIGGER: + return &animation->triggers; + default: + return nullptr; + } + } + return nullptr; + } + + Reference Anm2::layer_animation_add(Reference reference, std::string name, int spritesheetID, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.layers) : reference.itemID; + auto& layer = content.layers[id]; + + layer.name = !name.empty() ? name : layer.name; + layer.spritesheetID = content.spritesheets.contains(spritesheetID) ? spritesheetID : 0; + + auto add = [&](Animation* animation, int id) + { + animation->layerAnimations[id] = Item(); + animation->layerOrder.push_back(id); + }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.layerAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->layerAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } + + Reference Anm2::null_animation_add(Reference reference, std::string name, locale::Type locale) + { + auto id = reference.itemID == -1 ? map::next_id_get(content.nulls) : reference.itemID; + auto& null = content.nulls[id]; + + null.name = !name.empty() ? name : null.name; + + auto add = [&](Animation* animation, int id) { animation->nullAnimations[id] = Item(); }; + + if (locale == locale::GLOBAL) + { + for (auto& animation : animations.items) + if (!animation.nullAnimations.contains(id)) add(&animation, id); + } + else if (locale == locale::LOCAL) + { + if (auto animation = animation_get(reference)) + if (!animation->nullAnimations.contains(id)) add(animation, id); + } + + return {reference.animationIndex, LAYER, id}; + } +} \ No newline at end of file diff --git a/src/anm2/anm2_layers.cpp b/src/anm2/anm2_layers.cpp new file mode 100644 index 0000000..9a48ac1 --- /dev/null +++ b/src/anm2/anm2_layers.cpp @@ -0,0 +1,66 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::layer_add(int& id) + { + id = map::next_id_get(content.layers); + content.layers[id] = Layer(); + } + + std::set Anm2::layers_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->layerAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.layerAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.layers | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::layers_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Layer")) + { + if (errorString) *errorString = "No valid layer(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Layer"); element; element = element->NextSiblingElement("Layer")) + { + auto layer = Layer(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.layers); + content.layers[id] = layer; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_nulls.cpp b/src/anm2/anm2_nulls.cpp new file mode 100644 index 0000000..49ed6ce --- /dev/null +++ b/src/anm2/anm2_nulls.cpp @@ -0,0 +1,66 @@ +#include "anm2.h" + +#include + +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + void Anm2::null_add(int& id) + { + id = map::next_id_get(content.nulls); + content.nulls[id] = Null(); + } + + std::set Anm2::nulls_unused(Reference reference) + { + std::set used{}; + std::set unused{}; + + if (auto animation = animation_get(reference); animation) + for (auto& id : animation->nullAnimations | std::views::keys) + used.insert(id); + else + for (auto& animation : animations.items) + for (auto& id : animation.nullAnimations | std::views::keys) + used.insert(id); + + for (auto& id : content.nulls | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::nulls_deserialize(const std::string& string, merge::Type type, std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Null")) + { + if (errorString) *errorString = "No valid null(s)."; + return false; + } + + for (auto element = document.FirstChildElement("Null"); element; element = element->NextSiblingElement("Null")) + { + auto null = Null(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.nulls); + content.nulls[id] = null; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_sounds.cpp b/src/anm2/anm2_sounds.cpp new file mode 100644 index 0000000..299d64c --- /dev/null +++ b/src/anm2/anm2_sounds.cpp @@ -0,0 +1,75 @@ +#include "anm2.h" + +#include + +#include "filesystem_.h" +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + bool Anm2::sound_add(const std::string& directory, const std::string& path, int& id) + { + id = map::next_id_get(content.sounds); + content.sounds[id] = Sound(directory, path); + return true; + } + + std::vector Anm2::sound_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& [id, sound] : content.sounds) + labels.emplace_back(sound.path.string()); + return labels; + } + + std::set Anm2::sounds_unused() + { + std::set used; + for (auto& animation : animations.items) + for (auto& trigger : animation.triggers.frames) + if (content.sounds.contains(trigger.soundID)) used.insert(trigger.soundID); + + std::set unused; + for (auto& id : content.sounds | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + bool Anm2::sounds_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Sound")) + { + if (errorString) *errorString = "No valid sound(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Sound"); element; element = element->NextSiblingElement("Sound")) + { + auto sound = Sound(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.sounds); + content.sounds[id] = std::move(sound); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_spritesheets.cpp b/src/anm2/anm2_spritesheets.cpp new file mode 100644 index 0000000..9849db2 --- /dev/null +++ b/src/anm2/anm2_spritesheets.cpp @@ -0,0 +1,87 @@ +#include "anm2.h" + +#include + +#include "filesystem_.h" +#include "map_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Spritesheet* Anm2::spritesheet_get(int id) + { + return map::find(content.spritesheets, id); + } + + void Anm2::spritesheet_remove(int id) + { + content.spritesheets.erase(id); + } + + bool Anm2::spritesheet_add(const std::string& directory, const std::string& path, int& id) + { + Spritesheet spritesheet(directory, path); + if (!spritesheet.is_valid()) return false; + id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + return true; + } + + std::set Anm2::spritesheets_unused() + { + std::set used{}; + for (auto& layer : content.layers | std::views::values) + if (layer.is_spritesheet_valid()) used.insert(layer.spritesheetID); + + std::set unused{}; + for (auto& id : content.spritesheets | std::views::keys) + if (!used.contains(id)) unused.insert(id); + + return unused; + } + + std::vector Anm2::spritesheet_labels_get() + { + std::vector labels{}; + labels.emplace_back("None"); + for (auto& [id, spritesheet] : content.spritesheets) + labels.emplace_back(std::format(SPRITESHEET_FORMAT, id, spritesheet.path.c_str())); + return labels; + } + + bool Anm2::spritesheets_deserialize(const std::string& string, const std::string& directory, merge::Type type, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + int id{}; + + if (!document.FirstChildElement("Spritesheet")) + { + if (errorString) *errorString = "No valid spritesheet(s)."; + return false; + } + + filesystem::WorkingDirectory workingDirectory(directory); + + for (auto element = document.FirstChildElement("Spritesheet"); element; + element = element->NextSiblingElement("Spritesheet")) + { + auto spritesheet = Spritesheet(element, id); + if (type == merge::APPEND) id = map::next_id_get(content.spritesheets); + content.spritesheets[id] = std::move(spritesheet); + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } +} diff --git a/src/anm2/anm2_type.h b/src/anm2/anm2_type.h new file mode 100644 index 0000000..e5d15d6 --- /dev/null +++ b/src/anm2/anm2_type.h @@ -0,0 +1,84 @@ +#pragma once + +#include "icon.h" + +#include +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto ROOT_COLOR = glm::vec4(0.140f, 0.310f, 0.560f, 1.000f); + constexpr auto ROOT_COLOR_ACTIVE = glm::vec4(0.240f, 0.520f, 0.880f, 1.000f); + constexpr auto ROOT_COLOR_HOVERED = glm::vec4(0.320f, 0.640f, 1.000f, 1.000f); + + constexpr auto LAYER_COLOR = glm::vec4(0.640f, 0.320f, 0.110f, 1.000f); + constexpr auto LAYER_COLOR_ACTIVE = glm::vec4(0.840f, 0.450f, 0.170f, 1.000f); + constexpr auto LAYER_COLOR_HOVERED = glm::vec4(0.960f, 0.560f, 0.240f, 1.000f); + + constexpr auto NULL_COLOR = glm::vec4(0.140f, 0.430f, 0.200f, 1.000f); + constexpr auto NULL_COLOR_ACTIVE = glm::vec4(0.250f, 0.650f, 0.350f, 1.000f); + constexpr auto NULL_COLOR_HOVERED = glm::vec4(0.350f, 0.800f, 0.480f, 1.000f); + + constexpr auto TRIGGER_COLOR = glm::vec4(0.620f, 0.150f, 0.260f, 1.000f); + constexpr auto TRIGGER_COLOR_ACTIVE = glm::vec4(0.820f, 0.250f, 0.380f, 1.000f); + constexpr auto TRIGGER_COLOR_HOVERED = glm::vec4(0.950f, 0.330f, 0.490f, 1.000f); + +#define TYPE_LIST \ + X(NONE, "", "", resource::icon::NONE, glm::vec4(), glm::vec4(), glm::vec4()) \ + X(ROOT, "Root", "RootAnimation", resource::icon::ROOT, ROOT_COLOR, ROOT_COLOR_ACTIVE, ROOT_COLOR_HOVERED) \ + X(LAYER, "Layer", "LayerAnimation", resource::icon::LAYER, LAYER_COLOR, LAYER_COLOR_ACTIVE, LAYER_COLOR_HOVERED) \ + X(NULL_, "Null", "NullAnimation", resource::icon::NULL_, NULL_COLOR, NULL_COLOR_ACTIVE, NULL_COLOR_HOVERED) \ + X(TRIGGER, "Triggers", "Triggers", resource::icon::TRIGGERS, TRIGGER_COLOR, TRIGGER_COLOR_ACTIVE, \ + TRIGGER_COLOR_HOVERED) + + enum Type + { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) symbol, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_STRINGS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) string, + TYPE_LIST +#undef X + }; + + constexpr const char* TYPE_ITEM_STRINGS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) itemString, + TYPE_LIST +#undef X + }; + + constexpr resource::icon::Type TYPE_ICONS[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) icon, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) color, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR_ACTIVE[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) colorActive, + TYPE_LIST +#undef X + }; + + constexpr glm::vec4 TYPE_COLOR_HOVERED[] = { +#define X(symbol, string, itemString, icon, color, colorActive, colorHovered) colorHovered, + TYPE_LIST +#undef X + }; + + enum ChangeType + { + ADD, + SUBTRACT, + ADJUST + }; +} \ No newline at end of file diff --git a/src/anm2/content.cpp b/src/anm2/content.cpp new file mode 100644 index 0000000..ff007ed --- /dev/null +++ b/src/anm2/content.cpp @@ -0,0 +1,56 @@ +#include "content.h" + +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Content::Content(XMLElement* element) + { + int id{}; + + if (auto spritesheetsElement = element->FirstChildElement("Spritesheets")) + for (auto child = spritesheetsElement->FirstChildElement("Spritesheet"); child; + child = child->NextSiblingElement("Spritesheet")) + spritesheets[id] = Spritesheet(child, id); + + if (auto layersElement = element->FirstChildElement("Layers")) + for (auto child = layersElement->FirstChildElement("Layer"); child; child = child->NextSiblingElement("Layer")) + layers[id] = Layer(child, id); + + if (auto nullsElement = element->FirstChildElement("Nulls")) + for (auto child = nullsElement->FirstChildElement("Null"); child; child = child->NextSiblingElement("Null")) + nulls[id] = Null(child, id); + + if (auto eventsElement = element->FirstChildElement("Events")) + for (auto child = eventsElement->FirstChildElement("Event"); child; child = child->NextSiblingElement("Event")) + events[id] = Event(child, id); + } + + void Content::serialize(XMLDocument& document, XMLElement* parent) + { + auto element = document.NewElement("Content"); + + auto spritesheetsElement = document.NewElement("Spritesheets"); + for (auto& [id, spritesheet] : spritesheets) + spritesheet.serialize(document, spritesheetsElement, id); + element->InsertEndChild(spritesheetsElement); + + auto layersElement = document.NewElement("Layers"); + for (auto& [id, layer] : layers) + layer.serialize(document, layersElement, id); + element->InsertEndChild(layersElement); + + auto nullsElement = document.NewElement("Nulls"); + for (auto& [id, null] : nulls) + null.serialize(document, nullsElement, id); + element->InsertEndChild(nullsElement); + + auto eventsElement = document.NewElement("Events"); + for (auto& [id, event] : events) + event.serialize(document, eventsElement, id); + element->InsertEndChild(eventsElement); + + parent->InsertEndChild(element); + } + +} diff --git a/src/anm2/content.h b/src/anm2/content.h new file mode 100644 index 0000000..330c433 --- /dev/null +++ b/src/anm2/content.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "event.h" +#include "layer.h" +#include "null.h" +#include "sound.h" +#include "spritesheet.h" + +namespace anm2ed::anm2 +{ + struct Content + { + std::map spritesheets{}; + std::map layers{}; + std::map nulls{}; + std::map events{}; + std::map sounds{}; + + Content() = default; + + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + Content(tinyxml2::XMLElement*); + }; +} \ No newline at end of file diff --git a/src/anm2/event.cpp b/src/anm2/event.cpp new file mode 100644 index 0000000..7427897 --- /dev/null +++ b/src/anm2/event.cpp @@ -0,0 +1,36 @@ +#include "event.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Event::Event(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + } + + XMLElement* Event::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Event"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + return element; + } + + void Event::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Event::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/event.h b/src/anm2/event.h new file mode 100644 index 0000000..f86d35d --- /dev/null +++ b/src/anm2/event.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + class Event + { + public: + std::string name{"New Event"}; + int soundID{-1}; + + Event() = default; + Event(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/frame.cpp b/src/anm2/frame.cpp new file mode 100644 index 0000000..746a308 --- /dev/null +++ b/src/anm2/frame.cpp @@ -0,0 +1,128 @@ +#include "frame.h" + +#include "math_.h" +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Frame::Frame(XMLElement* element, Type type) + { + if (type != TRIGGER) + { + element->QueryFloatAttribute("XPosition", &position.x); + element->QueryFloatAttribute("YPosition", &position.y); + if (type == LAYER) + { + element->QueryFloatAttribute("XPivot", &pivot.x); + element->QueryFloatAttribute("YPivot", &pivot.y); + element->QueryFloatAttribute("XCrop", &crop.x); + element->QueryFloatAttribute("YCrop", &crop.y); + element->QueryFloatAttribute("Width", &size.x); + element->QueryFloatAttribute("Height", &size.y); + } + element->QueryFloatAttribute("XScale", &scale.x); + element->QueryFloatAttribute("YScale", &scale.y); + element->QueryIntAttribute("Delay", &delay); + element->QueryBoolAttribute("Visible", &isVisible); + xml::query_color_attribute(element, "RedTint", tint.r); + xml::query_color_attribute(element, "GreenTint", tint.g); + xml::query_color_attribute(element, "BlueTint", tint.b); + xml::query_color_attribute(element, "AlphaTint", tint.a); + xml::query_color_attribute(element, "RedOffset", colorOffset.r); + xml::query_color_attribute(element, "GreenOffset", colorOffset.g); + xml::query_color_attribute(element, "BlueOffset", colorOffset.b); + element->QueryFloatAttribute("Rotation", &rotation); + element->QueryBoolAttribute("Interpolated", &isInterpolated); + } + else + { + element->QueryIntAttribute("EventId", &eventID); + element->QueryIntAttribute("AtFrame", &atFrame); + } + } + + XMLElement* Frame::to_element(XMLDocument& document, Type type) + { + auto element = document.NewElement(type == TRIGGER ? "Trigger" : "Frame"); + + switch (type) + { + case ROOT: + case NULL_: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case LAYER: + element->SetAttribute("XPosition", position.x); + element->SetAttribute("YPosition", position.y); + element->SetAttribute("XPivot", pivot.x); + element->SetAttribute("YPivot", pivot.y); + element->SetAttribute("XCrop", crop.x); + element->SetAttribute("YCrop", crop.y); + element->SetAttribute("Width", size.x); + element->SetAttribute("Height", size.y); + element->SetAttribute("XScale", scale.x); + element->SetAttribute("YScale", scale.y); + element->SetAttribute("Delay", delay); + element->SetAttribute("Visible", isVisible); + element->SetAttribute("RedTint", math::float_to_uint8(tint.r)); + element->SetAttribute("GreenTint", math::float_to_uint8(tint.g)); + element->SetAttribute("BlueTint", math::float_to_uint8(tint.b)); + element->SetAttribute("AlphaTint", math::float_to_uint8(tint.a)); + element->SetAttribute("RedOffset", math::float_to_uint8(colorOffset.r)); + element->SetAttribute("GreenOffset", math::float_to_uint8(colorOffset.g)); + element->SetAttribute("BlueOffset", math::float_to_uint8(colorOffset.b)); + element->SetAttribute("Rotation", rotation); + element->SetAttribute("Interpolated", isInterpolated); + break; + case TRIGGER: + element->SetAttribute("EventId", eventID); + element->SetAttribute("AtFrame", atFrame); + break; + default: + break; + } + + return element; + } + + void Frame::serialize(XMLDocument& document, XMLElement* parent, Type type) + { + parent->InsertEndChild(to_element(document, type)); + } + + std::string Frame::to_string(Type type) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, type)); + return xml::document_to_string(document); + } + + void Frame::shorten() { delay = glm::clamp(--delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); } + + void Frame::extend() { delay = glm::clamp(++delay, FRAME_DELAY_MIN, FRAME_DELAY_MAX); } + + bool Frame::is_visible(Type type) + { + if (type == TRIGGER) + return isVisible && eventID > -1; + else + return isVisible; + } +} \ No newline at end of file diff --git a/src/anm2/frame.h b/src/anm2/frame.h new file mode 100644 index 0000000..f17a086 --- /dev/null +++ b/src/anm2/frame.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +#include "anm2_type.h" +#include "types.h" + +namespace anm2ed::anm2 +{ + constexpr auto FRAME_DELAY_MIN = 1; + constexpr auto FRAME_DELAY_MAX = 100000; + +#define MEMBERS \ + X(isVisible, bool, true) \ + X(isInterpolated, bool, false) \ + X(rotation, float, 0.0f) \ + X(delay, int, FRAME_DELAY_MIN) \ + X(atFrame, int, -1) \ + X(eventID, int, -1) \ + X(soundID, int, -1) \ + X(pivot, glm::vec2, {}) \ + X(crop, glm::vec2, {}) \ + X(position, glm::vec2, {}) \ + X(size, glm::vec2, {}) \ + X(scale, glm::vec2, glm::vec2(100.0f)) \ + X(colorOffset, glm::vec3, types::color::TRANSPARENT) \ + X(tint, glm::vec4, types::color::WHITE) + + class Frame + { + public: +#define X(name, type, ...) type name = __VA_ARGS__; + MEMBERS +#undef X + + Frame() = default; + Frame(tinyxml2::XMLElement*, Type); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Type); + std::string to_string(Type type); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type); + void shorten(); + void extend(); + bool is_visible(Type = NONE); + }; + + struct FrameChange + { +#define X(name, type, ...) std::optional name{}; + MEMBERS +#undef X + }; + +#undef MEMBERS + +} \ No newline at end of file diff --git a/src/anm2/info.cpp b/src/anm2/info.cpp new file mode 100644 index 0000000..2ea0433 --- /dev/null +++ b/src/anm2/info.cpp @@ -0,0 +1,40 @@ +#include "info.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Info::Info(XMLElement* element) + { + if (!element) return; + xml::query_string_attribute(element, "CreatedBy", &createdBy); + xml::query_string_attribute(element, "CreatedOn", &createdOn); + element->QueryIntAttribute("Fps", &fps); + element->QueryIntAttribute("Version", &version); + } + + XMLElement* Info::to_element(XMLDocument& document) + { + auto element = document.NewElement("Info"); + element->SetAttribute("CreatedBy", createdBy.c_str()); + element->SetAttribute("CreatedOn", createdOn.c_str()); + element->SetAttribute("Fps", fps); + element->SetAttribute("Version", version); + return element; + } + + void Info::serialize(XMLDocument& document, XMLElement* parent) + { + parent->InsertEndChild(to_element(document)); + } + + std::string Info::to_string() + { + XMLDocument document{}; + document.InsertEndChild(to_element(document)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/info.h b/src/anm2/info.h new file mode 100644 index 0000000..c2fd400 --- /dev/null +++ b/src/anm2/info.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto FPS_MIN = 1; + constexpr auto FPS_MAX = 120; + + class Info + { + public: + std::string createdBy{"robot"}; + std::string createdOn{}; + int fps = 30; + int version{}; + + Info() = default; + Info(tinyxml2::XMLElement*); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument& document); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*); + std::string to_string(); + }; +} \ No newline at end of file diff --git a/src/anm2/item.cpp b/src/anm2/item.cpp new file mode 100644 index 0000000..c569091 --- /dev/null +++ b/src/anm2/item.cpp @@ -0,0 +1,252 @@ +#include "item.h" +#include + +#include "vector_.h" +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; +using namespace glm; + +namespace anm2ed::anm2 +{ + Item::Item(XMLElement* element, Type type, int* id) + { + if (type == LAYER && id) element->QueryIntAttribute("LayerId", id); + if (type == NULL_ && id) element->QueryIntAttribute("NullId", id); + + element->QueryBoolAttribute("Visible", &isVisible); + + for (auto child = type == TRIGGER ? element->FirstChildElement("Trigger") : element->FirstChildElement("Frame"); + child; child = type == TRIGGER ? child->NextSiblingElement("Trigger") : child->NextSiblingElement("Frame")) + frames.push_back(Frame(child, type)); + } + + XMLElement* Item::to_element(XMLDocument& document, Type type, int id) + { + auto element = document.NewElement(TYPE_ITEM_STRINGS[type]); + + if (type == LAYER) element->SetAttribute("LayerId", id); + if (type == NULL_) element->SetAttribute("NullId", id); + if (type == LAYER || type == NULL_) element->SetAttribute("Visible", isVisible); + + for (auto& frame : frames) + frame.serialize(document, element, type); + + return element; + } + + void Item::serialize(XMLDocument& document, XMLElement* parent, Type type, int id) + { + parent->InsertEndChild(to_element(document, type, id)); + } + + std::string Item::to_string(Type type, int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, type, id)); + return xml::document_to_string(document); + } + + int Item::length(Type type) + { + int length{}; + + if (type == TRIGGER) + for (auto& frame : frames) + length = frame.atFrame > length ? frame.atFrame : length; + else + for (auto& frame : frames) + length += frame.delay; + + return length; + } + + Frame Item::frame_generate(float time, Type type) + { + Frame frame{}; + frame.isVisible = false; + + if (frames.empty()) return frame; + + Frame* frameNext = nullptr; + int delayCurrent = 0; + int delayNext = 0; + + for (auto [i, iFrame] : std::views::enumerate(frames)) + { + if (type == TRIGGER) + { + if ((int)time == iFrame.atFrame) + { + frame = iFrame; + break; + } + } + else + { + frame = iFrame; + + delayNext += frame.delay; + + if (time >= delayCurrent && time < delayNext) + { + if (i + 1 < (int)frames.size()) + frameNext = &frames[i + 1]; + else + frameNext = nullptr; + break; + } + + delayCurrent += frame.delay; + } + } + + if (type != TRIGGER && frame.isInterpolated && frameNext && frame.delay > 1) + { + auto interpolation = (time - delayCurrent) / (delayNext - delayCurrent); + + frame.rotation = glm::mix(frame.rotation, frameNext->rotation, interpolation); + frame.position = glm::mix(frame.position, frameNext->position, interpolation); + frame.scale = glm::mix(frame.scale, frameNext->scale, interpolation); + frame.colorOffset = glm::mix(frame.colorOffset, frameNext->colorOffset, interpolation); + frame.tint = glm::mix(frame.tint, frameNext->tint, interpolation); + } + + return frame; + } + + void Item::frames_change(FrameChange& change, ChangeType type, int start, int numberFrames) + { + auto useStart = numberFrames > -1 ? start : 0; + auto end = numberFrames > -1 ? start + numberFrames : (int)frames.size(); + end = glm::clamp(end, start, (int)frames.size()); + + for (int i = useStart; i < end; i++) + { + Frame& frame = frames[i]; + + if (change.isVisible) frame.isVisible = *change.isVisible; + if (change.isInterpolated) frame.isInterpolated = *change.isInterpolated; + + switch (type) + { + case ADJUST: + if (change.rotation) frame.rotation = *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, *change.delay); + if (change.crop) frame.crop = *change.crop; + if (change.pivot) frame.pivot = *change.pivot; + if (change.position) frame.position = *change.position; + if (change.size) frame.size = *change.size; + if (change.scale) frame.scale = *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(*change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(*change.tint, 0.0f, 1.0f); + break; + + case ADD: + if (change.rotation) frame.rotation += *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay + *change.delay); + if (change.crop) frame.crop += *change.crop; + if (change.pivot) frame.pivot += *change.pivot; + if (change.position) frame.position += *change.position; + if (change.size) frame.size += *change.size; + if (change.scale) frame.scale += *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset + *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint + *change.tint, 0.0f, 1.0f); + break; + + case SUBTRACT: + if (change.rotation) frame.rotation -= *change.rotation; + if (change.delay) frame.delay = std::max(FRAME_DELAY_MIN, frame.delay - *change.delay); + if (change.crop) frame.crop -= *change.crop; + if (change.pivot) frame.pivot -= *change.pivot; + if (change.position) frame.position -= *change.position; + if (change.size) frame.size -= *change.size; + if (change.scale) frame.scale -= *change.scale; + if (change.colorOffset) frame.colorOffset = glm::clamp(frame.colorOffset - *change.colorOffset, 0.0f, 1.0f); + if (change.tint) frame.tint = glm::clamp(frame.tint - *change.tint, 0.0f, 1.0f); + break; + } + } + } + + bool Item::frames_deserialize(const std::string& string, Type type, int start, std::set& indices, + std::string* errorString) + { + XMLDocument document{}; + + if (document.Parse(string.c_str()) == XML_SUCCESS) + { + if (!document.FirstChildElement("Frame")) + { + if (errorString) *errorString = "No valid frame(s)."; + return false; + } + + int count{}; + for (auto element = document.FirstChildElement("Frame"); element; element = element->NextSiblingElement("Frame")) + { + auto index = start + count; + frames.insert(frames.begin() + start + count, Frame(element, type)); + indices.insert(index); + count++; + } + + return true; + } + else if (errorString) + *errorString = document.ErrorStr(); + + return false; + } + + void Item::frames_bake(int index, int interval, bool isRoundScale, bool isRoundRotation) + { + if (!vector::in_bounds(frames, index)) return; + + Frame& frame = frames[index]; + if (frame.delay == FRAME_DELAY_MIN) return; + + Frame frameNext = vector::in_bounds(frames, index + 1) ? frames[index + 1] : frame; + + int delay{}; + int i = index; + + while (delay < frame.delay) + { + Frame baked = frame; + float interpolation = (float)delay / frame.delay; + baked.delay = std::min(interval, frame.delay - delay); + baked.isInterpolated = (i == index) ? frame.isInterpolated : false; + baked.rotation = glm::mix(frame.rotation, frameNext.rotation, interpolation); + baked.position = glm::mix(frame.position, frameNext.position, interpolation); + baked.scale = glm::mix(frame.scale, frameNext.scale, interpolation); + baked.colorOffset = glm::mix(frame.colorOffset, frameNext.colorOffset, interpolation); + baked.tint = glm::mix(frame.tint, frameNext.tint, interpolation); + if (isRoundScale) baked.scale = vec2(ivec2(baked.scale)); + if (isRoundRotation) baked.rotation = (int)baked.rotation; + + if (i == index) + frames[i] = baked; + else + frames.insert(frames.begin() + i, baked); + i++; + + delay += baked.delay; + } + } + + void Item::frames_generate_from_grid(ivec2 startPosition, ivec2 size, ivec2 pivot, int columns, int count, int delay) + { + for (int i = 0; i < count; i++) + { + Frame frame{}; + frame.delay = delay; + frame.pivot = pivot; + frame.size = size; + frame.crop = startPosition + ivec2(size.x * (i % columns), size.y * (i / columns)); + + frames.emplace_back(frame); + } + } +} \ No newline at end of file diff --git a/src/anm2/item.h b/src/anm2/item.h new file mode 100644 index 0000000..9bf0228 --- /dev/null +++ b/src/anm2/item.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "frame.h" + +namespace anm2ed::anm2 +{ + class Item + { + public: + std::vector frames{}; + bool isVisible{true}; + + Item() = default; + Item(tinyxml2::XMLElement*, Type, int* = nullptr); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, Type, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, Type, int = -1); + std::string to_string(Type, int = -1); + int length(Type); + Frame frame_generate(float, Type); + void frames_change(FrameChange&, ChangeType, int, int = 0); + bool frames_deserialize(const std::string&, Type, int, std::set&, std::string*); + void frames_bake(int, int, bool, bool); + void frames_generate_from_grid(glm::ivec2, glm::ivec2, glm::ivec2, int, int, int); + }; +} \ No newline at end of file diff --git a/src/anm2/layer.cpp b/src/anm2/layer.cpp new file mode 100644 index 0000000..5dbe7ba --- /dev/null +++ b/src/anm2/layer.cpp @@ -0,0 +1,43 @@ +#include "layer.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Layer::Layer(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryIntAttribute("SpritesheetId", &spritesheetID); + } + + XMLElement* Layer::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Layer"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + element->SetAttribute("SpritesheetId", spritesheetID); + return element; + } + + void Layer::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Layer::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } + + bool Layer::is_spritesheet_valid() + { + return spritesheetID > -1; + } +} \ No newline at end of file diff --git a/src/anm2/layer.h b/src/anm2/layer.h new file mode 100644 index 0000000..0ebc1fc --- /dev/null +++ b/src/anm2/layer.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto LAYER_FORMAT = "#{} {} (Spritesheet: #{})"; + constexpr auto LAYER_NO_SPRITESHEET_FORMAT = "#{} {} (No Spritesheet)"; + + class Layer + { + public: + std::string name{"New Layer"}; + int spritesheetID{}; + + Layer() = default; + Layer(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + bool is_spritesheet_valid(); + }; +} \ No newline at end of file diff --git a/src/anm2/null.cpp b/src/anm2/null.cpp new file mode 100644 index 0000000..272228a --- /dev/null +++ b/src/anm2/null.cpp @@ -0,0 +1,38 @@ +#include "null.h" + +#include "xml_.h" + +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Null::Null(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_string_attribute(element, "Name", &name); + element->QueryBoolAttribute("ShowRect", &isShowRect); + } + + XMLElement* Null::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Null"); + element->SetAttribute("Id", id); + element->SetAttribute("Name", name.c_str()); + if (isShowRect) element->SetAttribute("ShowRect", isShowRect); + return element; + } + + void Null::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Null::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } +} \ No newline at end of file diff --git a/src/anm2/null.h b/src/anm2/null.h new file mode 100644 index 0000000..1691be9 --- /dev/null +++ b/src/anm2/null.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +namespace anm2ed::anm2 +{ + constexpr auto NULL_FORMAT = "#{} {}"; + + class Null + { + public: + std::string name{"New Null"}; + bool isShowRect{}; + + Null() = default; + Null(tinyxml2::XMLElement*, int&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument& document, int id); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + std::string to_string(int); + }; +} \ No newline at end of file diff --git a/src/anm2/sound.cpp b/src/anm2/sound.cpp new file mode 100644 index 0000000..d6f9b8a --- /dev/null +++ b/src/anm2/sound.cpp @@ -0,0 +1,73 @@ +#include "sound.h" + +#include "filesystem_.h" +#include "xml_.h" + +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Sound::Sound(const Sound& other) : path(other.path) + { + audio = path.empty() ? Audio() : Audio(path.c_str()); + } + + Sound& Sound::operator=(const Sound& other) + { + if (this != &other) + { + path = other.path; + audio = path.empty() ? Audio() : Audio(path.c_str()); + } + return *this; + } + + Sound::Sound(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path) : this->path; + this->path = filesystem::path_lower_case_backslash_handle(this->path); + audio = Audio(this->path.c_str()); + } + + Sound::Sound(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_path_attribute(element, "Path", &path); + path = filesystem::path_lower_case_backslash_handle(path); + audio = Audio(path.c_str()); + } + + XMLElement* Sound::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Sound"); + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + return element; + } + + std::string Sound::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } + + void Sound::reload(const std::string& directory) + { + *this = Sound(directory, this->path); + } + + bool Sound::is_valid() + { + return audio.is_valid(); + } + + void Sound::play() + { + audio.play(); + } +} \ No newline at end of file diff --git a/src/anm2/sound.h b/src/anm2/sound.h new file mode 100644 index 0000000..951af67 --- /dev/null +++ b/src/anm2/sound.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "audio.h" + +namespace anm2ed::anm2 +{ + constexpr auto SOUND_FORMAT = "{}"; + + class Sound + { + public: + std::filesystem::path path{}; + resource::Audio audio{}; + + Sound() = default; + Sound(Sound&&) noexcept = default; + Sound& operator=(Sound&&) noexcept = default; + + Sound(const Sound&); + Sound& operator=(const Sound&); + Sound(tinyxml2::XMLElement*, int&); + Sound(const std::string&, const std::string&); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + std::string to_string(int); + void reload(const std::string&); + bool is_valid(); + void play(); + }; +} \ No newline at end of file diff --git a/src/anm2/spritesheet.cpp b/src/anm2/spritesheet.cpp new file mode 100644 index 0000000..7f0ce56 --- /dev/null +++ b/src/anm2/spritesheet.cpp @@ -0,0 +1,69 @@ +#include "spritesheet.h" + +#include "filesystem_.h" +#include "xml_.h" + +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace tinyxml2; + +namespace anm2ed::anm2 +{ + Spritesheet::Spritesheet(XMLElement* element, int& id) + { + if (!element) return; + element->QueryIntAttribute("Id", &id); + xml::query_path_attribute(element, "Path", &path); + // Spritesheet paths from Isaac Rebirth are made with the assumption that paths are case-insensitive + // However when using the resource dumper, the spritesheet paths are all lowercase (on Linux anyway) + // This will handle this case and make the paths OS-agnostic + path = filesystem::path_lower_case_backslash_handle(path); + texture = Texture(path); + } + + Spritesheet::Spritesheet(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path) : this->path; + this->path = filesystem::path_lower_case_backslash_handle(this->path); + texture = Texture(this->path); + } + + XMLElement* Spritesheet::to_element(XMLDocument& document, int id) + { + auto element = document.NewElement("Spritesheet"); + element->SetAttribute("Id", id); + element->SetAttribute("Path", path.c_str()); + return element; + } + + void Spritesheet::serialize(XMLDocument& document, XMLElement* parent, int id) + { + parent->InsertEndChild(to_element(document, id)); + } + + std::string Spritesheet::to_string(int id) + { + XMLDocument document{}; + document.InsertEndChild(to_element(document, id)); + return xml::document_to_string(document); + } + + bool Spritesheet::save(const std::string& directory, const std::string& path) + { + filesystem::WorkingDirectory workingDirectory(directory); + this->path = !path.empty() ? std::filesystem::relative(path).string() : this->path.string(); + return texture.write_png(this->path); + } + + void Spritesheet::reload(const std::string& directory) + { + *this = Spritesheet(directory, this->path); + } + + bool Spritesheet::is_valid() + { + return texture.is_valid(); + } + +} \ No newline at end of file diff --git a/src/anm2/spritesheet.h b/src/anm2/spritesheet.h new file mode 100644 index 0000000..6db08f9 --- /dev/null +++ b/src/anm2/spritesheet.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "texture.h" + +namespace anm2ed::anm2 +{ + constexpr auto SPRITESHEET_FORMAT_C = "#%d %s"; + constexpr auto SPRITESHEET_FORMAT = "#{} {}"; + + class Spritesheet + { + public: + std::filesystem::path path{}; + resource::Texture texture; + + Spritesheet() = default; + Spritesheet(tinyxml2::XMLElement*, int&); + Spritesheet(const std::string&, const std::string& = {}); + tinyxml2::XMLElement* to_element(tinyxml2::XMLDocument&, int); + std::string to_string(int id); + bool save(const std::string&, const std::string& = {}); + void serialize(tinyxml2::XMLDocument&, tinyxml2::XMLElement*, int); + void reload(const std::string&); + bool is_valid(); + }; +} \ No newline at end of file diff --git a/src/canvas.cpp b/src/canvas.cpp index 806ec9a..0ea9e2f 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,244 +1,351 @@ #include "canvas.h" -static void _canvas_framebuffer_set(Canvas* self, const ivec2& size) +#include +#include +#include +#include +#include + +#include "math_.h" +#include "texture.h" + +using namespace glm; +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace anm2ed::canvas; + +namespace anm2ed { - self->size = size; - self->previousSize = size; - - glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); + constexpr float AXIS_VERTICES[] = {-1.0f, 0.0f, 1.0f, 0.0f}; + constexpr float GRID_VERTICES[] = {-1.f, -1.f, 0.f, 0.f, 3.f, -1.f, 2.f, 0.f, -1.f, 3.f, 0.f, 2.f}; + constexpr float RECT_VERTICES[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + constexpr GLuint TEXTURE_INDICES[] = {0, 1, 2, 2, 3, 0}; - glBindTexture(GL_TEXTURE_2D, self->framebuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + Canvas::Canvas() = default; - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->framebuffer, 0); + Canvas::Canvas(vec2 size) + { + this->size = size; + previousSize = size; - glBindRenderbuffer(GL_RENDERBUFFER, self->rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self->size.x, self->size.y); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self->rbo); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void canvas_init(Canvas* self, const ivec2& size) -{ // Axis - glGenVertexArrays(1, &self->axisVAO); - glGenBuffers(1, &self->axisVBO); + glGenVertexArrays(1, &axisVAO); + glGenBuffers(1, &axisVBO); - glBindVertexArray(self->axisVAO); + glBindVertexArray(axisVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->axisVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_AXIS_VERTICES), CANVAS_AXIS_VERTICES, GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(f32), (void*)0); - - // Grid - glGenVertexArrays(1, &self->gridVAO); - glGenBuffers(1, &self->gridVBO); - - glBindVertexArray(self->gridVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); + glBindBuffer(GL_ARRAY_BUFFER, axisVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(AXIS_VERTICES), AXIS_VERTICES, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0); - - // Rect - glGenVertexArrays(1, &self->rectVAO); - glGenBuffers(1, &self->rectVBO); - - glBindVertexArray(self->rectVAO); - - glBindBuffer(GL_ARRAY_BUFFER, self->rectVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_RECT_VERTICES), CANVAS_RECT_VERTICES, GL_STATIC_DRAW); - - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); // Grid - glGenVertexArrays(1, &self->gridVAO); - glBindVertexArray(self->gridVAO); + glGenVertexArrays(1, &gridVAO); + glBindVertexArray(gridVAO); - glGenBuffers(1, &self->gridVBO); - glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_GRID_VERTICES), CANVAS_GRID_VERTICES, GL_STATIC_DRAW); + glGenBuffers(1, &gridVBO); + glBindBuffer(GL_ARRAY_BUFFER, gridVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GRID_VERTICES), GRID_VERTICES, GL_STATIC_DRAW); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, (void*)0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)0); + + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2)); glBindVertexArray(0); + // Rect + glGenVertexArrays(1, &rectVAO); + glGenBuffers(1, &rectVBO); + + glBindVertexArray(rectVAO); + + glBindBuffer(GL_ARRAY_BUFFER, rectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(RECT_VERTICES), RECT_VERTICES, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); + // Texture - glGenVertexArrays(1, &self->textureVAO); - glGenBuffers(1, &self->textureVBO); - glGenBuffers(1, &self->textureEBO); + glGenVertexArrays(1, &textureVAO); + glGenBuffers(1, &textureVBO); + glGenBuffers(1, &textureEBO); - glBindVertexArray(self->textureVAO); + glBindVertexArray(textureVAO); - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(f32) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4, nullptr, GL_DYNAMIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->textureEBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GL_TEXTURE_INDICES), GL_TEXTURE_INDICES, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, textureEBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(TEXTURE_INDICES), TEXTURE_INDICES, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(f32), (void*)(2 * sizeof(f32))); - glBindVertexArray(0); // Framebuffer - glGenTextures(1, &self->framebuffer); - glGenFramebuffers(1, &self->fbo); - glGenRenderbuffers(1, &self->rbo); - _canvas_framebuffer_set(self, size); + glGenTextures(1, &texture); + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); - self->isInit = true; -} + framebuffer_set(); + } -mat4 canvas_transform_get(Canvas* self, vec2 pan, f32 zoom, OriginType origin) -{ - f32 zoomFactor = PERCENT_TO_UNIT(zoom); - mat4 projection = glm::ortho(0.0f, (f32)self->size.x, 0.0f, (f32)self->size.y, -1.0f, 1.0f); - mat4 view = mat4{1.0f}; - vec2 size = vec2(self->size.x, self->size.y); - - switch (origin) + Canvas::~Canvas() + { + if (!is_valid()) return; + + glDeleteFramebuffers(1, &fbo); + glDeleteRenderbuffers(1, &rbo); + glDeleteTextures(1, &texture); + + glDeleteVertexArrays(1, &axisVAO); + glDeleteBuffers(1, &axisVBO); + + glDeleteVertexArrays(1, &gridVAO); + glDeleteBuffers(1, &gridVBO); + + glDeleteVertexArrays(1, &rectVAO); + glDeleteBuffers(1, &rectVBO); + } + + bool Canvas::is_valid() + { + return fbo != 0; + } + + void Canvas::framebuffer_set() + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, size.x, size.y); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + void Canvas::framebuffer_resize_check() + { + if (previousSize != size) { - case ORIGIN_TOP_LEFT: - view = glm::translate(view, vec3(pan, 0.0f)); - break; - default: - view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); - break; + framebuffer_set(); + previousSize = size; } + } + void Canvas::size_set(vec2 size) + { + this->size = size; + framebuffer_resize_check(); + } + + mat4 Canvas::transform_get(float zoom, vec2 pan) + { + auto zoomFactor = math::percent_to_unit(zoom); + auto projection = glm::ortho(0.0f, (float)size.x, 0.0f, (float)size.y, -1.0f, 1.0f); + auto view = mat4{1.0f}; + + view = glm::translate(view, vec3((size * 0.5f) + pan, 0.0f)); view = glm::scale(view, vec3(zoomFactor, zoomFactor, 1.0f)); - + return projection * view; -} + } -void canvas_clear(vec4& color) -{ - glClearColor(color.r, color.g, color.b, color.a); - glClear(GL_COLOR_BUFFER_BIT); -} + void Canvas::axes_render(Shader& shader, float zoom, vec2 pan, vec4 color) + { + auto originNDC = transform_get(zoom, pan) * vec4(0.0f, 0.0f, 0.0f, 1.0f); + originNDC /= originNDC.w; -void canvas_viewport_set(Canvas* self) -{ - glViewport(0, 0, (s32)self->size.x, (s32)self->size.y); -} + glUseProgram(shader.id); -void canvas_framebuffer_resize_check(Canvas* self) -{ - if (self->previousSize != self->size) - _canvas_framebuffer_set(self, self->size); -} + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), 1, value_ptr(color)); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); -void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color) -{ - mat4 inverseTransform = glm::inverse(transform); + glBindVertexArray(axisVAO); - glUseProgram(shader); + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_AXIS), 0); + glDrawArrays(GL_LINES, 0, 2); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_MODEL), 1, GL_FALSE, glm::value_ptr(inverseTransform)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_SIZE), size.x, size.y); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_OFFSET), offset.x, offset.y); - glUniform4f(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), color.r, color.g, color.b, color.a); + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_AXIS), 1); + glDrawArrays(GL_LINES, 0, 2); - glBindVertexArray(self->gridVAO); + glBindVertexArray(0); + glUseProgram(0); + } + + void Canvas::grid_render(Shader& shader, float zoom, vec2 pan, ivec2 size, ivec2 offset, vec4 color) + { + auto transform = glm::inverse(transform_get(zoom, pan)); + + glUseProgram(shader.id); + + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_SIZE), (float)size.x, (float)size.y); + glUniform2f(glGetUniformLocation(shader.id, shader::UNIFORM_OFFSET), (float)offset.x, (float)offset.y); + glUniform4f(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), color.r, color.g, color.b, color.a); + + glBindVertexArray(gridVAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); glUseProgram(0); -} + } + + void Canvas::texture_render(Shader& shader, GLuint& texture, mat4& transform, vec4 tint, vec3 colorOffset, + float* vertices) + { + glUseProgram(shader.id); + + glUniform1i(glGetUniformLocation(shader.id, shader::UNIFORM_TEXTURE), 0); + glUniform3fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TINT), 1, value_ptr(tint)); + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + + glBindVertexArray(textureVAO); + + glBindBuffer(GL_ARRAY_BUFFER, textureVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); -void canvas_texture_draw(Canvas* self, GLuint& shader, GLuint& texture, mat4& transform, const f32* vertices, vec4 tint, vec3 colorOffset) -{ - glUseProgram(shader); - - glBindVertexArray(self->textureVAO); - - glBindBuffer(GL_ARRAY_BUFFER, self->textureVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(CANVAS_TEXTURE_VERTICES), vertices, GL_DYNAMIC_DRAW); - glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_TEXTURE), 0); - glUniform3fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR_OFFSET), 1, value_ptr(colorOffset)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TINT), 1, value_ptr(tint)); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); - + glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0); -} + } -void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color) -{ - glUseProgram(shader); + void Canvas::rect_render(Shader& shader, const mat4& transform, const mat4& model, vec4 color, float dashLength, + float dashGap, float dashOffset) + { + glUseProgram(shader.id); - glBindVertexArray(self->rectVAO); + glUniformMatrix4fv(glGetUniformLocation(shader.id, shader::UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_MODEL); location != -1) + glUniformMatrix4fv(location, 1, GL_FALSE, value_ptr(model)); + glUniform4fv(glGetUniformLocation(shader.id, shader::UNIFORM_COLOR), 1, value_ptr(color)); - glUniformMatrix4fv(glGetUniformLocation(shader, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, value_ptr(transform)); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); + auto origin = model * vec4(0.0f, 0.0f, 0.0f, 1.0f); + auto edgeX = model * vec4(1.0f, 0.0f, 0.0f, 1.0f); + auto edgeY = model * vec4(0.0f, 1.0f, 0.0f, 1.0f); + auto axisX = vec2(edgeX - origin); + auto axisY = vec2(edgeY - origin); + + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_AXIS_X); location != -1) + glUniform2fv(location, 1, value_ptr(axisX)); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_AXIS_Y); location != -1) + glUniform2fv(location, 1, value_ptr(axisY)); + + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_LENGTH); location != -1) + glUniform1f(location, dashLength); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_GAP); location != -1) + glUniform1f(location, dashGap); + if (auto location = glGetUniformLocation(shader.id, shader::UNIFORM_DASH_OFFSET); location != -1) + glUniform1f(location, dashOffset); + + glBindVertexArray(rectVAO); glDrawArrays(GL_LINE_LOOP, 0, 4); glBindVertexArray(0); glUseProgram(0); -} + } + void Canvas::viewport_set() + { + glViewport(0, 0, size.x, size.y); + } -void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color) -{ - vec4 originNDC = transform * vec4(0.0f, 0.0f, 0.0f, 1.0f); - originNDC /= originNDC.w; + void Canvas::clear(vec4& color) + { + glClearColor(color.r, color.g, color.b, color.a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } - glUseProgram(shader); - glBindVertexArray(self->axisVAO); - glUniform4fv(glGetUniformLocation(shader, SHADER_UNIFORM_COLOR), 1, value_ptr(color)); - glUniform2f(glGetUniformLocation(shader, SHADER_UNIFORM_ORIGIN_NDC), originNDC.x, originNDC.y); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 0); - glDrawArrays(GL_LINES, 0, 2); - glUniform1i(glGetUniformLocation(shader, SHADER_UNIFORM_AXIS), 1); - glDrawArrays(GL_LINES, 0, 2); - glBindVertexArray(0); - glUseProgram(0); -} + void Canvas::bind() + { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + } -void canvas_bind(Canvas* self) -{ - glBindFramebuffer(GL_FRAMEBUFFER, self->fbo); -} - -void canvas_unbind(void) -{ + void Canvas::unbind() + { glBindFramebuffer(GL_FRAMEBUFFER, 0); -} + } -void canvas_free(Canvas* self) -{ - if (!self->isInit) return; + std::vector Canvas::pixels_get() + { + auto count = size.x * size.y * texture::CHANNELS; + std::vector pixels(count); - glDeleteFramebuffers(1, &self->fbo); - glDeleteRenderbuffers(1, &self->rbo); - glDeleteTextures(1, &self->framebuffer); - glDeleteVertexArrays(1, &self->axisVAO); - glDeleteVertexArrays(1, &self->rectVAO); - glDeleteVertexArrays(1, &self->gridVAO); - glDeleteVertexArrays(1, &self->textureVAO); - glDeleteBuffers(1, &self->axisVBO); - glDeleteBuffers(1, &self->rectVBO); - glDeleteBuffers(1, &self->gridVBO); - glDeleteBuffers(1, &self->textureVBO); - glDeleteBuffers(1, &self->textureEBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + return pixels; + } + + void Canvas::zoom_set(float& zoom, vec2& pan, vec2 focus, float step) + { + auto zoomFactor = math::percent_to_unit(zoom); + float newZoom = glm::clamp(math::round_nearest_multiple(zoom + step, step), ZOOM_MIN, ZOOM_MAX); + if (newZoom != zoom) + { + float newZoomFactor = math::percent_to_unit(newZoom); + pan += focus * (zoomFactor - newZoomFactor); + zoom = newZoom; + } + } + + vec4 Canvas::pixel_read(vec2 position, vec2 framebufferSize) + { + uint8_t rgba[4]{}; + + glBindTexture(GL_READ_FRAMEBUFFER, fbo); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(position.x, framebufferSize.y - 1 - position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + return vec4(math::uint8_to_float(rgba[0]), math::uint8_to_float(rgba[1]), math::uint8_to_float(rgba[2]), + math::uint8_to_float(rgba[3])); + } + + vec2 Canvas::position_translate(float& zoom, vec2& pan, vec2 position) + { + auto zoomFactor = math::percent_to_unit(zoom); + return (position - pan - (size * 0.5f)) / zoomFactor; + } + + void Canvas::set_to_rect(float& zoom, vec2& pan, vec4 rect) + { + if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) + { + f32 scaleX = size.x / rect.z; + f32 scaleY = size.y / rect.w; + f32 fitScale = std::min(scaleX, scaleY); + + zoom = math::unit_to_percent(fitScale); + + vec2 rectCenter = {rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f}; + pan = -rectCenter * fitScale; + } + } } \ No newline at end of file diff --git a/src/canvas.h b/src/canvas.h index 06a9d2f..8865d5a 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -1,45 +1,37 @@ #pragma once -#include "resources.h" +#include +#include -#define CANVAS_ZOOM_MIN 1.0f -#define CANVAS_ZOOM_MAX 2000.0f -#define CANVAS_ZOOM_DEFAULT 100.0f -#define CANVAS_ZOOM_STEP 100.0f -#define CANVAS_GRID_MIN 1 -#define CANVAS_GRID_MAX 1000 -#define CANVAS_GRID_DEFAULT 32 +#include "shader.h" -const inline vec2 CANVAS_PIVOT_SIZE = {4, 4}; -const inline vec2 CANVAS_SCALE_DEFAULT = {1.0f, 1.0f}; - -const inline f32 CANVAS_AXIS_VERTICES[] = {-1.0f, 1.0f}; - -const inline f32 CANVAS_GRID_VERTICES[] = +namespace anm2ed::canvas { - -1.0f, -1.0f, - 3.0f, -1.0f, - -1.0f, 3.0f -}; + constexpr float TEXTURE_VERTICES[] = {0, 0, 0.0f, 0.0f, 1, 0, 1.0f, 0.0f, 1, 1, 1.0f, 1.0f, 0, 1, 0.0f, 1.0f}; -const inline f32 CANVAS_RECT_VERTICES[] = -{ - 0, 0, - 1, 0, - 1, 1, - 0, 1 -}; + constexpr auto PIVOT_SIZE = glm::vec2(8, 8); + constexpr auto ZOOM_MIN = 1.0f; + constexpr auto ZOOM_MAX = 2000.0f; + constexpr auto POSITION_FORMAT = "Position: ({:8}, {:8})"; -const inline f32 CANVAS_TEXTURE_VERTICES[] = -{ - 0, 0, 0.0f, 0.0f, - 1, 0, 1.0f, 0.0f, - 1, 1, 1.0f, 1.0f, - 0, 1, 0.0f, 1.0f -}; + constexpr auto DASH_LENGTH = 4.0f; + constexpr auto DASH_GAP = 1.0f; + constexpr auto DASH_OFFSET = 1.0f; -struct Canvas + constexpr auto STEP = 1.0f; + constexpr auto STEP_FAST = 5.0f; + + constexpr auto GRID_SIZE_MIN = 1; + constexpr auto GRID_SIZE_MAX = 10000; + constexpr auto GRID_OFFSET_MIN = 0; + constexpr auto GRID_OFFSET_MAX = 10000; +} + +namespace anm2ed { + class Canvas + { + public: GLuint fbo{}; GLuint rbo{}; GLuint axisVAO{}; @@ -48,48 +40,37 @@ struct Canvas GLuint rectVBO{}; GLuint gridVAO{}; GLuint gridVBO{}; - GLuint framebuffer{}; GLuint textureVAO{}; GLuint textureVBO{}; GLuint textureEBO{}; - ivec2 size{}; - ivec2 previousSize{}; - bool isInit = false; -}; + GLuint texture{}; + glm::vec2 previousSize{}; + glm::vec2 size{}; -#define UV_VERTICES(uvMin, uvMax) \ -{ \ - 0, 0, uvMin.x, uvMin.y, \ - 1, 0, uvMax.x, uvMin.y, \ - 1, 1, uvMax.x, uvMax.y, \ - 0, 1, uvMin.x, uvMax.y \ + Canvas(); + Canvas(glm::vec2); + ~Canvas(); + bool is_valid(); + void framebuffer_set(); + void framebuffer_resize_check(); + void size_set(glm::vec2); + glm::vec4 pixel_read(glm::vec2, glm::vec2); + glm::mat4 transform_get(float = 100.0f, glm::vec2 = {}); + void axes_render(resource::Shader&, float, glm::vec2, glm::vec4 = glm::vec4(1.0f)); + void grid_render(resource::Shader&, float, glm::vec2, glm::ivec2 = glm::ivec2(32, 32), glm::ivec2 = {}, + glm::vec4 = glm::vec4(1.0f)); + void texture_render(resource::Shader&, GLuint&, glm::mat4&, glm::vec4 = glm::vec4(1.0f), glm::vec3 = {}, + float* = (float*)canvas::TEXTURE_VERTICES); + void rect_render(resource::Shader&, const glm::mat4&, const glm::mat4&, glm::vec4 = glm::vec4(1.0f), + float dashLength = canvas::DASH_LENGTH, float dashGap = canvas::DASH_GAP, + float dashOffset = canvas::DASH_OFFSET); + void viewport_set(); + void clear(glm::vec4&); + void bind(); + void unbind(); + void zoom_set(float&, glm::vec2&, glm::vec2, float); + glm::vec2 position_translate(float&, glm::vec2&, glm::vec2); + void set_to_rect(float& zoom, glm::vec2& pan, glm::vec4 rect); + std::vector pixels_get(); + }; } - -#define ATLAS_UV_MIN(type) (ATLAS_POSITION(type) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_MAX(type) ((ATLAS_POSITION(type) + ATLAS_SIZE(type)) / TEXTURE_ATLAS_SIZE) -#define ATLAS_UV_ARGS(type) ATLAS_UV_MIN(type), ATLAS_UV_MAX(type) -#define ATLAS_UV_VERTICES(type) UV_VERTICES(ATLAS_UV_MIN(type), ATLAS_UV_MAX(type)) - -mat4 canvas_transform_get(Canvas* self, vec2 pan, f32 zoom, OriginType origin); -void canvas_axes_draw(Canvas* self, GLuint& shader, mat4& transform, vec4& color); -void canvas_bind(Canvas* self); -void canvas_clear(vec4& color); -void canvas_draw(Canvas* self); -void canvas_free(Canvas* self); -void canvas_grid_draw(Canvas* self, GLuint& shader, mat4& transform, ivec2& size, ivec2& offset, vec4& color); -void canvas_init(Canvas* self, const ivec2& size); -void canvas_rect_draw(Canvas* self, const GLuint& shader, const mat4& transform, const vec4& color); -void canvas_framebuffer_resize_check(Canvas* self); -void canvas_unbind(void); -void canvas_viewport_set(Canvas* self); - -void canvas_texture_draw -( - Canvas* self, - GLuint& shader, - GLuint& texture, - mat4& transform, - const f32* vertices = CANVAS_TEXTURE_VERTICES, - vec4 tint = COLOR_OPAQUE, - vec3 colorOffset = COLOR_OFFSET_NONE -); \ No newline at end of file diff --git a/src/clipboard.cpp b/src/clipboard.cpp index 874db01..e66150d 100644 --- a/src/clipboard.cpp +++ b/src/clipboard.cpp @@ -1,113 +1,25 @@ #include "clipboard.h" -void clipboard_copy(Clipboard* self) +#include + +namespace anm2ed { - std::string clipboardText{}; - - auto clipboard_text_set = [&]() - { - if (!SDL_SetClipboardText(clipboardText.c_str())) - log_warning(std::format(CLIPBOARD_TEXT_SET_WARNING, SDL_GetError())); - }; - - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, reference); - if (!frame) break; - anm2_frame_serialize_to_string(frame, reference->itemType, &clipboardText); - clipboard_text_set(); - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - Anm2Animation* animation = map_find(self->anm2->animations, *id); - if (!animation) break; - anm2_animation_serialize_to_string(animation, &clipboardText); - clipboard_text_set(); - break; - } - break; - default: - break; - } -} + std::string Clipboard::get() + { + auto text = SDL_GetClipboardText(); + auto string = std::string(text); + SDL_free(text); -void clipboard_cut(Clipboard* self) -{ - clipboard_copy(self); + return string; + } - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - anm2_frame_remove(self->anm2, reference); - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - anm2_animation_remove(self->anm2, *id); - break; - } - default: - break; - } -} + bool Clipboard::is_empty() + { + return get().empty(); + } -bool clipboard_paste(Clipboard* self) -{ - auto clipboard_string = [&]() - { - char* clipboardText = SDL_GetClipboardText(); - std::string clipboardString = std::string(clipboardText); - SDL_free(clipboardText); - return clipboardString; - }; - - switch (self->type) - { - case CLIPBOARD_FRAME: - { - Anm2Reference* reference = std::get_if(&self->location); - if (!reference) break; - Anm2Frame frame; - if (anm2_frame_deserialize_from_xml(&frame, clipboard_string())) - anm2_frame_add(self->anm2, &frame, reference); - else return false; - break; - } - case CLIPBOARD_ANIMATION: - { - s32* id = std::get_if(&self->location); - if (!id) break; - Anm2Animation animation; - if (anm2_animation_deserialize_from_xml(&animation, clipboard_string())) - anm2_animation_add(self->anm2, &animation, *id); - else return false; - break; - } - default: - break; - } - - return true; -} - -void clipboard_init(Clipboard* self, Anm2* anm2) -{ - self->anm2 = anm2; -} - -bool clipboard_is_value(void) -{ - return SDL_HasClipboardText(); + void Clipboard::set(const std::string& string) + { + SDL_SetClipboardText(string.data()); + } } \ No newline at end of file diff --git a/src/clipboard.h b/src/clipboard.h index d269ce7..9e8ec8b 100644 --- a/src/clipboard.h +++ b/src/clipboard.h @@ -1,27 +1,14 @@ #pragma once -#include "anm2.h" +#include -#define CLIPBOARD_TEXT_SET_WARNING "Unable to set clipboard text! ({})" - -enum ClipboardType +namespace anm2ed { - CLIPBOARD_NONE, - CLIPBOARD_FRAME, - CLIPBOARD_ANIMATION -}; - -using ClipboardLocation = std::variant; - -struct Clipboard -{ - Anm2* anm2 = nullptr; - ClipboardType type; - ClipboardLocation location; -}; - -bool clipboard_is_value(void); -void clipboard_copy(Clipboard* self); -void clipboard_cut(Clipboard* self); -bool clipboard_paste(Clipboard* self); -void clipboard_init(Clipboard* self, Anm2* anm2); \ No newline at end of file + class Clipboard + { + public: + bool is_empty(); + std::string get(); + void set(const std::string&); + }; +} diff --git a/src/dialog.cpp b/src/dialog.cpp index f3a1449..c46d064 100644 --- a/src/dialog.cpp +++ b/src/dialog.cpp @@ -1,91 +1,87 @@ #include "dialog.h" #ifdef _WIN32 - #include + #include +#elif __unix__ +#else + #include "toast.h" #endif -static void _dialog_callback(void* userdata, const char* const* filelist, s32 filter) +#include + +namespace anm2ed::dialog { - Dialog* self; + void callback(void* userData, const char* const* filelist, int filter) + { + auto self = (Dialog*)(userData); - self = (Dialog*)userdata; - - if (filelist && filelist[0] && strlen(filelist[0]) > 0) - { - self->path = filelist[0]; - self->isSelected = true; - self->selectedFilter = filter; - } - else - { - self->isSelected = false; - self->selectedFilter = INDEX_NONE; - } + if (filelist && filelist[0] && strlen(filelist[0]) > 0) + { + self->path = filelist[0]; + self->selectedFilter = filter; + } + else + self->selectedFilter = -1; + } } -void dialog_init(Dialog* self, SDL_Window* window) -{ - self->window = window; -} +using namespace anm2ed::dialog; -void dialog_anm2_open(Dialog* self) +namespace anm2ed { - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr, false); - self->type = DIALOG_ANM2_OPEN; -} -void dialog_anm2_save(Dialog* self) -{ - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_ANM2, std::size(DIALOG_FILE_FILTER_ANM2), nullptr); - self->type = DIALOG_ANM2_SAVE; -} + Dialog::Dialog(SDL_Window* window) + { + *this = Dialog(); + this->window = window; + } -void dialog_spritesheet_add(Dialog* self) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->type = DIALOG_SPRITESHEET_ADD; -} + void Dialog::file_open(dialog::Type type) + { + SDL_ShowOpenFileDialog(callback, this, window, FILTERS[TYPE_FILTERS[type]], std::size(FILTERS[TYPE_FILTERS[type]]), + nullptr, false); + this->type = type; + } -void dialog_spritesheet_replace(Dialog* self, s32 id) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_PNG, std::size(DIALOG_FILE_FILTER_PNG), nullptr, false); - self->replaceID = id; - self->type = DIALOG_SPRITESHEET_REPLACE; -} + void Dialog::file_save(dialog::Type type) + { + SDL_ShowSaveFileDialog(callback, this, window, FILTERS[TYPE_FILTERS[type]], std::size(FILTERS[TYPE_FILTERS[type]]), + nullptr); + this->type = type; + } -void dialog_render_path_set(Dialog* self, RenderType type) -{ - SDL_DialogFileFilter filter = DIALOG_RENDER_FILE_FILTERS[type]; + void Dialog::folder_open(dialog::Type type) + { + SDL_ShowOpenFolderDialog(callback, this, window, nullptr, false); + this->type = type; + } - if (type == RENDER_PNG) - SDL_ShowOpenFolderDialog(_dialog_callback, self, self->window, nullptr, false); - else - SDL_ShowSaveFileDialog(_dialog_callback, self, self->window, &filter, 1, nullptr); - self->type = DIALOG_RENDER_PATH_SET; -} - -void dialog_ffmpeg_path_set(Dialog* self) -{ - SDL_ShowOpenFileDialog(_dialog_callback, self, self->window, DIALOG_FILE_FILTER_FFMPEG, std::size(DIALOG_FILE_FILTER_FFMPEG), nullptr, false); - self->type = DIALOG_FFMPEG_PATH_SET; -} - -void dialog_explorer_open(const std::string& path) -{ + void Dialog::file_explorer_open(const std::string& path) + { #ifdef _WIN32 - ShellExecuteA(NULL, DIALOG_FILE_EXPLORER_COMMAND, path.c_str(), NULL, NULL, SW_SHOWNORMAL); -#else - char command[DIALOG_FILE_EXPLORER_COMMAND_SIZE]; - snprintf(command, sizeof(command), DIALOG_FILE_EXPLORER_COMMAND, path.c_str()); - system(command); + ShellExecuteA(NULL, "open", path.c_str(), NULL, NULL, SW_SHOWNORMAL); +#elif __unix__ + system(std::format("xdg-open \"{}\" &", path).c_str()); +#else + toasts.info("Operation not supported."); #endif -} + } -void -dialog_reset(Dialog* self) -{ - self->replaceID = ID_NONE; - self->type = DIALOG_NONE; - self->path.clear(); - self->isSelected = false; -} \ No newline at end of file + void Dialog::reset() + { + *this = Dialog(this->window); + } + + bool Dialog::is_selected(dialog::Type type) + { + return this->type == type && !path.empty(); + } + + void Dialog::set_string_to_selected_path(std::string& string, dialog::Type type) + { + if (type == NONE) return; + if (!is_selected(type)) return; + string = path; + reset(); + } +}; diff --git a/src/dialog.h b/src/dialog.h index f624e17..dfd214e 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -1,71 +1,91 @@ #pragma once -#include "render.h" -#include "window.h" +#include -#define DIALOG_FILE_EXPLORER_COMMAND_SIZE 512 +#include -#ifdef _WIN32 -#define DIALOG_FILE_EXPLORER_COMMAND "open" -#else -#define DIALOG_FILE_EXPLORER_COMMAND "xdg-open \"%s\" &" -#endif - -const SDL_DialogFileFilter DIALOG_FILE_FILTER_ANM2[] = +namespace anm2ed::dialog { - {"Anm2 file", "anm2;xml"} -}; - -const SDL_DialogFileFilter DIALOG_FILE_FILTER_PNG[] = -{ - {"PNG image", "png"} -}; - -const SDL_DialogFileFilter DIALOG_RENDER_FILE_FILTERS[] = -{ - {"PNG image", "png"}, - {"GIF image", "gif"}, - {"WebM video", "webm"}, - {"MP4 video", "mp4"} -}; - -const SDL_DialogFileFilter DIALOG_FILE_FILTER_FFMPEG[] = -{ -#ifdef _WIN32 - {"Executable", "exe"} +#if defined(_WIN32) + #define EXECUTABLE_FILTER {"Executable", "exe"} #else - {"Executable", ""} + #define EXECUTABLE_FILTER {"Executable", "*"} #endif -}; -enum DialogType -{ - DIALOG_NONE, - DIALOG_ANM2_OPEN, - DIALOG_ANM2_SAVE, - DIALOG_SPRITESHEET_ADD, - DIALOG_SPRITESHEET_REPLACE, - DIALOG_RENDER_PATH_SET, - DIALOG_FFMPEG_PATH_SET -}; +#define FILTER_LIST \ + X(NO_FILTER, {}) \ + X(ANM2, {"Anm2 file", "anm2;xml"}) \ + X(PNG, {"PNG image", "png"}) \ + X(SOUND, {"WAV file;OGG file", "wav;ogg"}) \ + X(GIF, {"GIF image", "gif"}) \ + X(WEBM, {"WebM video", "webm"}) \ + X(MP4, {"MP4 video", "MP4"}) \ + X(EXECUTABLE, EXECUTABLE_FILTER) -struct Dialog + enum Filter + { +#define X(symbol, ...) symbol, + FILTER_LIST +#undef X + }; + + constexpr SDL_DialogFileFilter FILTERS[][1] = { +#define X(symbol, ...) {__VA_ARGS__}, + FILTER_LIST +#undef X + }; + +#undef FILTER_LIST + +#define DIALOG_LIST \ + X(NONE, NO_FILTER) \ + X(ANM2_NEW, ANM2) \ + X(ANM2_OPEN, ANM2) \ + X(ANM2_SAVE, ANM2) \ + X(SOUND_OPEN, SOUND) \ + X(SPRITESHEET_OPEN, PNG) \ + X(SPRITESHEET_REPLACE, PNG) \ + X(FFMPEG_PATH_SET, EXECUTABLE) \ + X(PNG_DIRECTORY_SET, NO_FILTER) \ + X(GIF_PATH_SET, GIF) \ + X(WEBM_PATH_SET, WEBM) \ + X(MP4_PATH_SET, MP4) + + enum Type + { +#define X(symbol, filter) symbol, + DIALOG_LIST +#undef X + }; + + constexpr Filter TYPE_FILTERS[] = { +#define X(symbol, filter) filter, + DIALOG_LIST +#undef X + }; + +#undef DIALOG_LIST +} + +namespace anm2ed { - SDL_Window* window = nullptr; - s32 selectedFilter = ID_NONE; + + class Dialog + { + public: + SDL_Window* window{}; std::string path{}; - s32 replaceID = ID_NONE; - DialogType type = DIALOG_NONE; - bool isSelected = false; -}; + dialog::Type type{dialog::NONE}; + int selectedFilter{-1}; -void dialog_init(Dialog* self, SDL_Window* window); -void dialog_anm2_open(Dialog* self); -void dialog_spritesheet_add(Dialog* self); -void dialog_spritesheet_replace(Dialog* self, s32 id); -void dialog_anm2_save(Dialog* self); -void dialog_render_path_set(Dialog* self, RenderType type); -void dialog_render_directory_set(Dialog* self); -void dialog_ffmpeg_path_set(Dialog* self); -void dialog_reset(Dialog* self); -void dialog_explorer_open(const std::string& path); \ No newline at end of file + Dialog() = default; + Dialog(SDL_Window*); + void file_open(dialog::Type type); + void file_save(dialog::Type type); + void folder_open(dialog::Type type); + bool is_selected(dialog::Type type); + void reset(); + void file_explorer_open(const std::string&); + void set_string_to_selected_path(std::string& set, dialog::Type type); + }; +} diff --git a/src/document.cpp b/src/document.cpp new file mode 100644 index 0000000..c602acb --- /dev/null +++ b/src/document.cpp @@ -0,0 +1,290 @@ +#include "document.h" + +#include + +#include "filesystem_.h" +#include "log.h" +#include "toast.h" + +using namespace anm2ed::anm2; +using namespace anm2ed::imgui; +using namespace anm2ed::types; +using namespace anm2ed::util; + +using namespace glm; + +namespace anm2ed +{ + Document::Document(const std::string& path, bool isNew, std::string* errorString) + { + if (!filesystem::path_is_exist(path)) return; + + if (isNew) + anm2 = anm2::Anm2(); + else + { + anm2 = Anm2(path, errorString); + if (errorString && !errorString->empty()) return; + } + + this->path = path; + clean(); + change(Document::ALL); + } + + Document::Document(Document&& other) noexcept + : path(std::move(other.path)), snapshots(std::move(other.snapshots)), current(snapshots.current), + anm2(current.anm2), reference(current.reference), playback(current.playback), animation(current.animation), + merge(current.merge), event(current.event), layer(current.layer), null(current.null), sound(current.sound), + spritesheet(current.spritesheet), message(current.message), previewZoom(other.previewZoom), + previewPan(other.previewPan), editorPan(other.editorPan), editorZoom(other.editorZoom), + overlayIndex(other.overlayIndex), hoveredFrame(other.hoveredFrame), hash(other.hash), saveHash(other.saveHash), + autosaveHash(other.autosaveHash), lastAutosaveTime(other.lastAutosaveTime), isOpen(other.isOpen), + isForceDirty(other.isForceDirty), isAnimationPreviewSet(other.isAnimationPreviewSet), + isSpritesheetEditorSet(other.isSpritesheetEditorSet) + { + } + + Document& Document::operator=(Document&& other) noexcept + { + if (this != &other) + { + path = std::move(other.path); + snapshots = std::move(other.snapshots); + previewZoom = other.previewZoom; + previewPan = other.previewPan; + editorPan = other.editorPan; + editorZoom = other.editorZoom; + overlayIndex = other.overlayIndex; + hoveredFrame = other.hoveredFrame; + hash = other.hash; + saveHash = other.saveHash; + autosaveHash = other.autosaveHash; + lastAutosaveTime = other.lastAutosaveTime; + isOpen = other.isOpen; + isForceDirty = other.isForceDirty; + isAnimationPreviewSet = other.isAnimationPreviewSet; + isSpritesheetEditorSet = other.isSpritesheetEditorSet; + } + return *this; + } + + bool Document::save(const std::string& path, std::string* errorString) + { + this->path = !path.empty() ? path : this->path.string(); + + if (anm2.serialize(this->path, errorString)) + { + toasts.info(std::format("Saved document to: {}", this->path.string())); + clean(); + return true; + } + else if (errorString) + toasts.warning(std::format("Could not save document to: {} ({})", this->path.string(), *errorString)); + + return false; + } + + std::filesystem::path Document::autosave_path_get() + { + return directory_get() / std::string("." + filename_get().string() + ".autosave"); + } + + std::filesystem::path Document::path_from_autosave_get(std::filesystem::path& path) + { + auto fileName = path.filename().string(); + if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); + + auto restorePath = path.parent_path() / fileName; + restorePath.replace_extension(""); + + return path; + } + + bool Document::autosave(std::string* errorString) + { + auto autosavePath = autosave_path_get(); + if (anm2.serialize(autosavePath, errorString)) + { + autosaveHash = hash; + lastAutosaveTime = 0.0f; + toasts.info("Autosaving..."); + logger.info(std::format("Autosaved document to: {}", autosavePath.string())); + return true; + } + else if (errorString) + toasts.warning(std::format("Could not autosave document to: {} ({})", autosavePath.string(), *errorString)); + + return false; + } + + void Document::hash_set() + { + hash = anm2.hash(); + } + + void Document::clean() + { + saveHash = anm2.hash(); + hash = saveHash; + lastAutosaveTime = 0.0f; + isForceDirty = false; + } + + void Document::change(ChangeType type) + { + hash_set(); + + auto layers_set = [&]() { layer.unused = anm2.layers_unused(); }; + auto nulls_set = [&]() { null.unused = anm2.nulls_unused(); }; + auto events_set = [&]() + { + event.unused = anm2.events_unused(); + event.labels_set(anm2.event_labels_get()); + }; + + auto animations_set = [&]() { animation.labels_set(anm2.animation_labels_get()); }; + + auto spritesheets_set = [&]() + { + spritesheet.unused = anm2.spritesheets_unused(); + spritesheet.labels_set(anm2.spritesheet_labels_get()); + }; + + auto sounds_set = [&]() + { + sound.unused = anm2.sounds_unused(); + sound.labels_set(anm2.sound_labels_get()); + + for (auto& animation : anm2.animations.items) + for (auto& trigger : animation.triggers.frames) + if (!anm2.content.sounds.contains(trigger.soundID)) trigger.soundID = -1; + }; + + switch (type) + { + case LAYERS: + layers_set(); + break; + case NULLS: + nulls_set(); + break; + case EVENTS: + events_set(); + break; + case SPRITESHEETS: + spritesheets_set(); + break; + case SOUNDS: + sounds_set(); + break; + case ANIMATIONS: + animations_set(); + break; + case ALL: + layers_set(); + nulls_set(); + events_set(); + spritesheets_set(); + animations_set(); + sounds_set(); + break; + default: + break; + } + } + + bool Document::is_dirty() + { + return hash != saveHash; + } + + bool Document::is_autosave_dirty() + { + return hash != autosaveHash; + } + + std::filesystem::path Document::directory_get() + { + return path.parent_path(); + } + + std::filesystem::path Document::filename_get() + { + return path.filename(); + } + + bool Document::is_valid() + { + return !path.empty(); + } + + anm2::Frame* Document::frame_get() + { + return anm2.frame_get(reference); + } + + anm2::Item* Document::item_get() + { + return anm2.item_get(reference); + } + + anm2::Animation* Document::animation_get() + { + return anm2.animation_get(reference); + } + + anm2::Spritesheet* Document::spritesheet_get() + { + return anm2.spritesheet_get(spritesheet.reference); + } + + void Document::spritesheet_add(const std::string& path) + { + auto add = [&]() + { + int id{}; + if (anm2.spritesheet_add(directory_get(), path, id)) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + this->spritesheet.selection = {id}; + toasts.info(std::format("Initialized spritesheet #{}: {}", id, spritesheet.path.string())); + } + else + toasts.error(std::format("Failed to initialize spritesheet: {}", path)); + }; + + DOCUMENT_EDIT_PTR(this, "Add Spritesheet", Document::SPRITESHEETS, add()); + } + + void Document::snapshot(const std::string& message) + { + this->message = message; + snapshots.push(current); + } + + void Document::undo() + { + snapshots.undo(); + toasts.info(std::format("Undo: {}", message)); + change(Document::ALL); + } + + void Document::redo() + { + snapshots.redo(); + toasts.info(std::format("Redo: {}", message)); + change(Document::ALL); + } + + bool Document::is_able_to_undo() + { + return !snapshots.undoStack.is_empty(); + } + + bool Document::is_able_to_redo() + { + return !snapshots.redoStack.is_empty(); + } + +} diff --git a/src/document.h b/src/document.h new file mode 100644 index 0000000..545d153 --- /dev/null +++ b/src/document.h @@ -0,0 +1,111 @@ +#pragma once + +#include + +#include "snapshots.h" + +#include + +namespace anm2ed +{ + + class Document + { + public: + enum ChangeType + { + LAYERS, + NULLS, + SPRITESHEETS, + EVENTS, + ANIMATIONS, + ITEMS, + FRAMES, + SOUNDS, + ALL, + COUNT + }; + + std::filesystem::path path{}; + + Snapshots snapshots{}; + Snapshot& current = snapshots.current; + + anm2::Anm2& anm2 = current.anm2; + anm2::Reference& reference = current.reference; + Playback& playback = current.playback; + Storage& animation = current.animation; + Storage& merge = current.merge; + Storage& event = current.event; + Storage& layer = current.layer; + Storage& null = current.null; + Storage& sound = current.sound; + Storage& spritesheet = current.spritesheet; + std::string& message = current.message; + + float previewZoom{200}; + glm::vec2 previewPan{}; + glm::vec2 editorPan{}; + float editorZoom{200}; + int overlayIndex{-1}; + + anm2::Reference hoveredFrame{}; + + uint64_t hash{}; + uint64_t saveHash{}; + uint64_t autosaveHash{}; + double lastAutosaveTime{}; + bool isOpen{true}; + bool isForceDirty{false}; + bool isAnimationPreviewSet{false}; + bool isSpritesheetEditorSet{false}; + + Document(const std::string&, bool = false, std::string* = nullptr); + Document(const Document&) = delete; + Document& operator=(const Document&) = delete; + Document(Document&&) noexcept; + Document& operator=(Document&&) noexcept; + bool save(const std::string& = {}, std::string* = nullptr); + void hash_set(); + void clean(); + void on_change(); + void change(ChangeType); + bool is_dirty(); + bool is_autosave_dirty(); + std::filesystem::path directory_get(); + std::filesystem::path filename_get(); + bool is_valid(); + + anm2::Frame* frame_get(); + anm2::Item* item_get(); + anm2::Spritesheet* spritesheet_get(); + anm2::Animation* animation_get(); + + void spritesheet_add(const std::string&); + + bool autosave(std::string* = nullptr); + std::filesystem::path autosave_path_get(); + std::filesystem::path path_from_autosave_get(std::filesystem::path&); + + void snapshot(const std::string& message); + void undo(); + void redo(); + bool is_able_to_undo(); + bool is_able_to_redo(); + }; + +#define DOCUMENT_EDIT(document, message, changeType, body) \ + { \ + document.snapshot(message); \ + body; \ + document.change(changeType); \ + } + +#define DOCUMENT_EDIT_PTR(document, message, changeType, body) \ + { \ + document->snapshot(message); \ + body; \ + document->change(changeType); \ + } + +} diff --git a/src/editor.cpp b/src/editor.cpp deleted file mode 100644 index 02e2a13..0000000 --- a/src/editor.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "editor.h" - -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, vec2()); -} - -void editor_draw(Editor* self) -{ - ivec2& gridSize = self->settings->editorGridSize; - ivec2& gridOffset = self->settings->editorGridOffset; - vec4& gridColor = self->settings->editorGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->editorPan, self->settings->editorZoom, ORIGIN_TOP_LEFT); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->editorBackgroundColor); - - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->spritesheetID)) - { - Texture& texture = spritesheet->texture; - - mat4 spritesheetTransform = transform * quad_model_get(texture.size); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, spritesheetTransform); - - if (self->settings->editorIsBorder) - canvas_rect_draw(&self->canvas, shaderLine, spritesheetTransform, EDITOR_BORDER_COLOR); - - Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, self->reference); - - if (frame) - { - mat4 cropTransform = transform * quad_model_get(frame->size, frame->crop); - canvas_rect_draw(&self->canvas, shaderLine, cropTransform, EDITOR_FRAME_COLOR); - - mat4 pivotTransform = transform * quad_model_get(CANVAS_PIVOT_SIZE, frame->crop + frame->pivot, CANVAS_PIVOT_SIZE * 0.5f); - f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, EDITOR_PIVOT_COLOR); - } - } - - if (self->settings->editorIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - - canvas_unbind(); -} - -void editor_free(Editor* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file diff --git a/src/editor.h b/src/editor.h deleted file mode 100644 index 8963e0b..0000000 --- a/src/editor.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "canvas.h" -#include "resources.h" -#include "settings.h" - -#define EDITOR_ZOOM_MIN 1.0f -#define EDITOR_ZOOM_MAX 1000.0f -#define EDITOR_ZOOM_STEP 25.0 -#define EDITOR_GRID_MIN 1 -#define EDITOR_GRID_MAX 1000 -#define EDITOR_GRID_OFFSET_MIN 0 -#define EDITOR_GRID_OFFSET_MAX 100 - -static const vec4 EDITOR_BORDER_COLOR = COLOR_OPAQUE; -static const vec4 EDITOR_FRAME_COLOR = COLOR_RED; -static const vec4 EDITOR_PIVOT_COLOR = COLOR_PINK; - -struct Editor -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - GLuint fbo; - GLuint rbo; - GLuint gridVAO; - GLuint gridVBO; - GLuint texture; - GLuint textureEBO; - GLuint textureVAO; - GLuint textureVBO; - GLuint borderVAO; - GLuint borderVBO; - s32 spritesheetID = ID_NONE; -}; - -void editor_init(Editor* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void editor_draw(Editor* self); -void editor_free(Editor* self); \ No newline at end of file diff --git a/src/ffmpeg.cpp b/src/ffmpeg.cpp deleted file mode 100644 index 36edf68..0000000 --- a/src/ffmpeg.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "ffmpeg.h" - -bool -ffmpeg_render -( - const std::string& ffmpegPath, - const std::string& outputPath, - const std::vector& frames, - ivec2 size, - s32 fps, - enum RenderType type -) -{ - if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || outputPath.empty()) return false; - - std::string command{}; - - switch (type) - { - case RENDER_GIF: - command = std::format(FFMPEG_GIF_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_WEBM: - command = std::format(FFMPEG_WEBM_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - case RENDER_MP4: - command = std::format(FFMPEG_MP4_FORMAT, ffmpegPath, size.x, size.y, fps, outputPath); - break; - default: - break; - } - -#if _WIN32 - command = string_quote(command); -#endif - - log_command(command); - - FILE* fp = POPEN(command.c_str(), PWRITE_MODE); - - if (!fp) - { - log_error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); - return false; - } - - size_t frameBytes = size.x * size.y * TEXTURE_CHANNELS; - - for (const auto& frame : frames) - { - std::vector rgba = texture_download(&frame); - - if (rgba.size() != frameBytes) - { - PCLOSE(fp); - return false; - } - - if (fwrite(rgba.data(), 1, frameBytes, fp) != frameBytes) - { - PCLOSE(fp); - return false; - } - } - - const int code = PCLOSE(fp); - - return (code == 0); -} \ No newline at end of file diff --git a/src/ffmpeg.h b/src/ffmpeg.h deleted file mode 100644 index 2747a57..0000000 --- a/src/ffmpeg.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "render.h" -#include "texture.h" - -#define FFMPEG_POPEN_ERROR "popen() (for FFmpeg) failed!\n{}" - -static constexpr const char* FFMPEG_GIF_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-lavfi \"split[s0][s1];" -"[s0]palettegen=stats_mode=full[p];" -"[s1][p]paletteuse=dither=floyd_steinberg\" " -"-loop 0 \"{4}\""; - -static constexpr const char* FFMPEG_WEBM_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 " -"-auto-alt-ref 0 -an \"{4}\""; - -static constexpr const char* FFMPEG_MP4_FORMAT = -"\"{0}\" -y " -"-f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0 " -"-vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" " -"-c:v libx265 -crf 20 -preset slow " -"-tag:v hvc1 -movflags +faststart -an \"{4}\""; - -bool -ffmpeg_render -( - const std::string& ffmpegPath, - const std::string& outputPath, - const std::vector& frames, - ivec2 size, - s32 fps, - enum RenderType type -); \ No newline at end of file diff --git a/src/generate_preview.cpp b/src/generate_preview.cpp deleted file mode 100644 index 7faa101..0000000 --- a/src/generate_preview.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "generate_preview.h" - -void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, GENERATE_PREVIEW_SIZE); -} - -void generate_preview_draw(GeneratePreview* self) -{ - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - const mat4 transform = canvas_transform_get(&self->canvas, {}, CANVAS_ZOOM_DEFAULT, ORIGIN_CENTER); - - vec2 startPosition = {self->settings->generateStartPosition.x, self->settings->generateStartPosition.y}; - vec2 size = {self->settings->generateSize.x, self->settings->generateSize.y}; - vec2 pivot = {self->settings->generatePivot.x, self->settings->generatePivot.y}; - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); - - if (item) - { - if (Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[self->reference->itemID].spritesheetID)) - { - Texture& texture = spritesheet->texture; - - const s32 index = std::clamp((s32)(self->time * count), 0, count); - const s32 row = index / columns; - const s32 column = index % columns; - vec2 crop = startPosition + vec2(size.x * column, size.y * row); - - vec2 textureSize = vec2(texture.size); - vec2 uvMin = (crop + vec2(0.5f)) / textureSize; - vec2 uvMax = (crop + size - vec2(0.5f)) / textureSize; - f32 vertices[] = UV_VERTICES(uvMin, uvMax); - - mat4 generateTransform = transform * quad_model_get(size, {}, pivot); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, generateTransform, vertices, COLOR_OPAQUE, COLOR_OFFSET_NONE); - } - } - - canvas_unbind(); -} - -void generate_preview_free(GeneratePreview* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file diff --git a/src/generate_preview.h b/src/generate_preview.h deleted file mode 100644 index fa1b576..0000000 --- a/src/generate_preview.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "resources.h" -#include "settings.h" -#include "canvas.h" - -#define GENERATE_PREVIEW_TIME_MIN 0.0f -#define GENERATE_PREVIEW_TIME_MAX 1.0f - -const vec2 GENERATE_PREVIEW_SIZE = {325, 215}; - -struct GeneratePreview -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - Canvas canvas; - f32 time{}; -}; - -void generate_preview_init(GeneratePreview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void generate_preview_draw(GeneratePreview* self); -void generate_preview_free(GeneratePreview* self); \ No newline at end of file diff --git a/src/imgui.cpp b/src/imgui.cpp deleted file mode 100644 index c6203fa..0000000 --- a/src/imgui.cpp +++ /dev/null @@ -1,3246 +0,0 @@ -#include "imgui.h" - -static bool _imgui_chord_pressed(ImGuiKeyChord chord) -{ - if (chord == IMGUI_CHORD_NONE) return false; - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - if (key == ImGuiKey_None) return false; - if (key < ImGuiKey_NamedKey_BEGIN || key >= ImGuiKey_NamedKey_END) return false; - - return ImGui::IsKeyChordPressed(chord); -} - -static const char* _imgui_f32_format_get(const ImguiItem& item, f32& value) -{ - if (item.isEmptyFormat) return ""; - return f32_format_get(value); -} - -static const char* _imgui_vec2_format_get(const ImguiItem& item, vec2& value) -{ - if (item.isEmptyFormat) return ""; - return vec2_format_get(value); -} - -static bool _imgui_window_color_from_position_get(SDL_Window* self, const vec2& position, vec4& color) -{ - ImGuiIO& io = ImGui::GetIO(); - ivec2 fbPosition = {(s32)(position.x * io.DisplayFramebufferScale.x), (s32)(position.y * io.DisplayFramebufferScale.y)}; - ivec2 size{}; - SDL_GetWindowSizeInPixels(self, &size.x, &size.y); - - if (fbPosition.x < 0 || fbPosition.y < 0 || fbPosition.x >= size.x || fbPosition.y >= size.y) return false; - - uint8_t rgba[4]; - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(fbPosition.x, size.y - 1 - fbPosition.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - - color = vec4(U8_TO_FLOAT(rgba[0]), U8_TO_FLOAT(rgba[1]), U8_TO_FLOAT(rgba[2]), U8_TO_FLOAT(rgba[3])); - - return true; -} - -static void _imgui_anm2_open(Imgui* self, const std::string& path) -{ - imgui_anm2_new(self); - - if (anm2_deserialize(self->anm2, path)) - { - window_title_from_path_set(self->window, path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); - } - else - imgui_log_push(self, std::format(IMGUI_LOG_FILE_OPEN_FORMAT, path)); -} - -static void _imgui_spritesheet_add(Imgui* self, const std::string& path) -{ - if (self->anm2->path.empty()) - { - imgui_log_push(self, IMGUI_LOG_NO_ANM2_PATH); - return; - } - - imgui_snapshot(self, IMGUI_ACTION_ADD_SPRITESHEET); - - std::filesystem::path workingPath = std::filesystem::current_path(); - std::string spritesheetPath = path; - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - spritesheetPath = std::filesystem::relative(path, anm2WorkingPath).string(); - s32 id = map_next_id_get(self->anm2->spritesheets); - self->anm2->spritesheets[id] = Anm2Spritesheet{}; - self->anm2->spritesheets[id].path = spritesheetPath; - texture_from_path_init(&self->anm2->spritesheets[id].texture, spritesheetPath); - - std::filesystem::current_path(workingPath); -} - -static bool _imgui_is_window_hovered(void) -{ - return ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); -} - -static bool _imgui_is_window_hovered_and_click(void) -{ - return _imgui_is_window_hovered() && ImGui::IsMouseClicked(0); -} - -static bool _imgui_is_window_hovered_and_click_no_anm2_path(Imgui* self) -{ - return _imgui_is_window_hovered_and_click() && self->anm2->path.empty(); -} - -static bool _imgui_is_no_click_on_item(void) -{ - return ImGui::IsMouseClicked(0) && !ImGui::IsAnyItemHovered(); -} - -static bool _imgui_is_input_begin(void) -{ - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_RENAME) || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)); -} - -static bool _imgui_is_input_default(void) -{ - return ImGui::IsItemHovered() && (ImGui::IsKeyPressed(IMGUI_INPUT_DEFAULT) || ImGui::IsMouseClicked(IMGUI_MOUSE_DEFAULT)); -} - -static bool _imgui_is_focus_window(const std::string& focus) -{ - ImGuiContext* ctx = ImGui::GetCurrentContext(); - if (!ctx || !ctx->NavWindow) return false; - - std::string_view name(ctx->NavWindow->Name); - return name.find(focus) != std::string_view::npos; -} - -static void _imgui_atlas(const AtlasType& self, Imgui* imgui) -{ - ImGui::Image(imgui->resources->atlas.id, ATLAS_SIZE(self), ATLAS_UV_ARGS(self)); -} - -static ImVec2 _imgui_item_size_get(const ImguiItem& self, ImguiItemType type) -{ - ImVec2 size = self.size; - - switch (type) - { - case IMGUI_ATLAS_BUTTON: - size = self.is_size() ? self.size : ImVec2(ATLAS_SIZE(self.atlas)); - break; - default: - if (self.is_row()) - size.x = (ImGui::GetWindowSize().x - (ImGui::GetStyle().ItemSpacing.x * (self.rowCount + 1))) / self.rowCount; - else if (self.isSizeToText) - size.x = (ImGui::CalcTextSize(self.label_get().c_str()).x + ImGui::GetStyle().FramePadding.x); - else if (!self.is_size()) - size.x = ImGui::CalcItemWidth(); - break; - } - - return size; -} - -static void _imgui_item_pre(const ImguiItem& self, ImguiItemType type) -{ - ImVec2 size = _imgui_item_size_get(self, type); - - switch (type) - { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_CHILD: - case IMGUI_CONFIRM_POPUP: - break; - default: - ImGui::BeginDisabled(self.isDisabled); - } - - switch (type) - { - case IMGUI_CHILD: - if (self.color.is_normal()) ImGui::PushStyleColor(ImGuiCol_ChildBg, self.color.normal); - break; - case IMGUI_INPUT_INT: - case IMGUI_INPUT_TEXT: - case IMGUI_INPUT_FLOAT: - case IMGUI_DRAG_FLOAT: - case IMGUI_SLIDER_FLOAT: - case IMGUI_COLOR_EDIT: - ImGui::SetNextItemWidth(size.x); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.is_border()) - { - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, self.border); - if (self.color.is_border()) ImGui::PushStyleColor(ImGuiCol_Border, self.color.border); - } - if (self.color.is_normal()) ImGui::PushStyleColor(ImGuiCol_Button, self.color.normal); - if (self.color.is_active()) ImGui::PushStyleColor(ImGuiCol_ButtonActive, self.color.active); - if (self.color.is_hovered()) ImGui::PushStyleColor(ImGuiCol_ButtonHovered, self.color.hovered); - if (self.isSelected) - { - if (self.color.is_active()) - ImGui::PushStyleColor(ImGuiCol_Button, self.color.active); - else - ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]); - } - break; - default: - break; - } -} - -static void _imgui_item_post(const ImguiItem& self, Imgui* imgui, ImguiItemType type, bool& isActivated) -{ - if (self.is_mnemonic() && !self.isMnemonicDisabled) - { - ImVec2 position = ImGui::GetItemRectMin(); - ImFont* font = ImGui::GetFont(); - f32 fontSize = ImGui::GetFontSize(); - const char* start = self.label.c_str(); - const char* charPointer = start + self.mnemonicIndex; - - position.x += ImGui::GetStyle().FramePadding.x; - - f32 offset = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, start, charPointer).x; - f32 charWidth = font->CalcTextSizeA(fontSize, FLT_MAX, 0.0f, charPointer, charPointer + 1).x; - - ImVec2 lineStart = ImVec2(position.x + offset, position.y + fontSize + 1.0f); - ImVec2 lineEnd = ImVec2(lineStart.x + charWidth, lineStart.y); - - ImU32 color = ImGui::GetColorU32(ImGuiCol_Text); - ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, color, 1.0f); - - if (_imgui_chord_pressed(ImGuiMod_Alt | self.mnemonicKey)) - { - if (!self.isDisabled) isActivated = true; - imgui_close_current_popup(imgui); - } - } - - if (self.isUseItemActivated && !self.isDisabled) isActivated = ImGui::IsItemActivated(); - - if - ( - imgui->isContextualActionsEnabled && _imgui_chord_pressed(self.chord_get()) && - (self.is_focus_window() && _imgui_is_focus_window(self.focusWindow)) - ) - if (!self.isDisabled) isActivated = true; - - if (self.is_tooltip() && ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) - ImGui::SetTooltip(self.tooltip_get().c_str()); - - if (isActivated) - { - if (self.is_undoable()) imgui_snapshot(imgui, self.snapshotAction); - if (self.is_function()) self.function(imgui); - - if (self.is_popup()) - { - imgui->pendingPopup = self.popup; - imgui->pendingPopupType = self.popupType; - imgui->pendingPopupPosition = ImVec2(ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y + ImGui::GetItemRectSize().y); - } - } - - switch (type) - { - case IMGUI_CHILD: - if (self.color.is_normal()) ImGui::PopStyleColor(); - break; - case IMGUI_BUTTON: - case IMGUI_ATLAS_BUTTON: - if (self.is_border()) - { - ImGui::PopStyleVar(); - if (self.color.is_border()) ImGui::PopStyleColor(); - } - if (self.color.is_normal()) ImGui::PopStyleColor(); - if (self.color.is_active()) ImGui::PopStyleColor(); - if (self.color.is_hovered()) ImGui::PopStyleColor(); - if (self.isSelected) ImGui::PopStyleColor(); - break; - default: - break; - } - - switch (type) - { - case IMGUI_ITEM: - case IMGUI_TEXT: - case IMGUI_WINDOW: - case IMGUI_DOCKSPACE: - case IMGUI_CHILD: - case IMGUI_CONFIRM_POPUP: - break; - default: - ImGui::EndDisabled(); - } - - if (self.isSameLine) ImGui::SameLine(); - if (self.isSeparator) ImGui::Separator(); -} - -#define IMGUI_ITEM_FUNCTION(NAME, TYPE, FUNCTION) \ -static bool NAME(ImguiItem self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_VOID_FUNCTION(NAME, TYPE, FUNCTION) \ -static void NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - bool isActivated = false; \ - _imgui_item_pre(self, type); \ - ([&] { FUNCTION; })(); \ - _imgui_item_post(self, imgui, type, isActivated); \ -} - -#define IMGUI_ITEM_VALUE_FUNCTION(NAME, TYPE, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - VALUE value = inValue; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (_imgui_is_input_default()) \ - { \ - value = VALUE(self.value); \ - isActivated = true; \ - } \ - _imgui_item_post(self, imgui, type, isActivated); \ - inValue = value; \ - return isActivated; \ -} - -#define IMGUI_ITEM_VALUE_CLAMP_FUNCTION(NAME, TYPE, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - VALUE value = inValue; \ - _imgui_item_pre(self, type); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (_imgui_is_input_default()) \ - { \ - value = VALUE(self.value); \ - isActivated = true; \ - } \ - if (self.is_range()) value = glm::clamp(value, VALUE(self.min), VALUE(self.max)); \ - _imgui_item_post(self, imgui, type, isActivated); \ - inValue = value; \ - return isActivated; \ -} - -#define IMGUI_ITEM_CUSTOM_FUNCTION(NAME, TYPE, BODY) \ -static bool NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { BODY } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_CUSTOM_FUNCTION_WITH_VALUE(NAME, TYPE, VALUE, BODY) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& inValue) \ -{ \ - ImguiItemType type = TYPE; \ - _imgui_item_pre(self, type); \ - bool isActivated = false; \ - do { BODY } while (0); \ - _imgui_item_post(self, imgui, type, isActivated); \ - return isActivated; \ -} - -#define IMGUI_ITEM_ATLAS_FUNCTION(NAME, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui) \ -{ \ - _imgui_atlas(self.atlas, imgui); \ - ImGui::SameLine(); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - return isActivated; \ -} - -#define IMGUI_ITEM_ATLAS_VALUE_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& value) \ -{ \ - _imgui_atlas(self.atlas, imgui); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - return isActivated; \ -} - -#define IMGUI_ITEM_CHECKBOX_FUNCTION(NAME, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, bool& boolValue) \ -{ \ - ImguiItem checkboxItem = self.copy \ - ({.label = std::format(IMGUI_INVISIBLE_FORMAT, self.label), .isMnemonicDisabled = true}); \ - checkboxItem.isDisabled = false; \ - checkboxItem.isSeparator = false; \ - checkboxItem.value = 0; \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&] { return FUNCTION; })(); \ - if (isActivated) boolValue = !boolValue; \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, Imgui* imgui, VALUE& value, bool& boolValue) \ -{ \ - ImguiItem checkboxItem = self.copy \ - ({.label = std::format(IMGUI_INVISIBLE_FORMAT, self.label), .isMnemonicDisabled = true}); \ - checkboxItem.isDisabled = false; \ - checkboxItem.isSeparator = false; \ - checkboxItem.value = 0; \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_AND_CHECKBOX_FUNCTION(NAME, VALUE, FUNCTION) \ -static bool NAME(const ImguiItem& self, const ImguiItem& checkboxItem, Imgui* imgui, VALUE& value, bool& boolValue) \ -{ \ - bool isCheckboxActivated = _imgui_checkbox(checkboxItem, imgui, boolValue); \ - ImGui::SameLine(); \ - bool isActivated = ([&](VALUE& value) { return FUNCTION; })(value); \ - if (isCheckboxActivated) isActivated = true; \ - return isActivated; \ -} - -#define IMGUI_ITEM_DISABLED_GET(VALUE, ITEM, CONDITION) ImguiItem VALUE = ITEM; VALUE.isDisabled = CONDITION; - -IMGUI_ITEM_FUNCTION(_imgui_begin, IMGUI_WINDOW, ImGui::Begin(self.label_get().c_str(), nullptr, self.flags)); -#define IMGUI_BEGIN_OR_RETURN(item, imgui) if (!_imgui_begin(item, imgui)) { _imgui_end(); return; } -static void _imgui_end(void){ImGui::End();} -IMGUI_ITEM_VOID_FUNCTION(_imgui_dockspace, IMGUI_DOCKSPACE, ImGui::DockSpace(ImGui::GetID(self.label_get().c_str()), self.size, self.flags)); -IMGUI_ITEM_FUNCTION(_imgui_begin_child, IMGUI_CHILD, ImGui::BeginChild(self.label_get().c_str(), self.size, self.flags, self.windowFlags)); -static void _imgui_end_child(void) {ImGui::EndChild(); } -IMGUI_ITEM_VOID_FUNCTION(_imgui_text, IMGUI_TEXT, ImGui::Text(self.label_get().c_str())); -IMGUI_ITEM_FUNCTION(_imgui_button, IMGUI_BUTTON, ImGui::Button(self.label_get().c_str(), _imgui_item_size_get(self, type))); -IMGUI_ITEM_FUNCTION(_imgui_begin_table, IMGUI_TABLE, ImGui::BeginTable(self.label_get().c_str(), self.value, self.flags)); -static void _imgui_end_table(void) {ImGui::EndTable(); } -static void _imgui_table_setup_column(const char* text) {ImGui::TableSetupColumn(text); } -static void _imgui_table_headers_row(void) {ImGui::TableHeadersRow(); } -static void _imgui_table_next_row(void) {ImGui::TableNextRow(); } -static void _imgui_table_set_column_index(s32 index) {ImGui::TableSetColumnIndex(index); } -IMGUI_ITEM_FUNCTION(_imgui_selectable, IMGUI_SELECTABLE, ImGui::Selectable(self.label_get().c_str(), self.isSelected, self.flags, _imgui_item_size_get(self, type))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_radio_button, IMGUI_RADIO_BUTTON, s32, ImGui::RadioButton(self.label_get().c_str(), &value, self.value)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_button, IMGUI_COLOR_BUTTON, vec4, ImGui::ColorButton(self.label_get().c_str(), ImVec4(value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_checkbox, IMGUI_CHECKBOX, bool, ImGui::Checkbox(self.label_get().c_str(), &value)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int, IMGUI_INPUT_INT, s32, ImGui::InputInt(self.label_get().c_str(), &value, self.step, self.stepFast, self.flags)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_int2, IMGUI_INPUT_INT, ivec2, ImGui::InputInt2(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_VALUE_CLAMP_FUNCTION(_imgui_input_float, IMGUI_INPUT_FLOAT, f32, ImGui::InputFloat(self.label_get().c_str(), &value, self.step, self.stepFast, _imgui_f32_format_get(self, value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_slider_float, IMGUI_SLIDER_FLOAT, f32, ImGui::SliderFloat(self.label_get().c_str(), &value, self.min, self.max, _imgui_f32_format_get(self, value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float, IMGUI_DRAG_FLOAT, f32, ImGui::DragFloat(self.label_get().c_str(), &value, self.speed, self.min, self.max, _imgui_f32_format_get(self, value))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_drag_float2, IMGUI_DRAG_FLOAT, vec2, ImGui::DragFloat2(self.label_get().c_str(), value_ptr(value), self.speed, self.min, self.max, _imgui_vec2_format_get(self, value))); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit3, IMGUI_COLOR_EDIT, vec3, ImGui::ColorEdit3(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_VALUE_FUNCTION(_imgui_color_edit4, IMGUI_COLOR_EDIT, vec4, ImGui::ColorEdit4(self.label_get().c_str(), value_ptr(value), self.flags)); -IMGUI_ITEM_CHECKBOX_FUNCTION(_imgui_checkbox_selectable, _imgui_selectable(self, imgui)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_checkbox, bool, _imgui_checkbox(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_input_int, s32, _imgui_input_int(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float, f32, _imgui_drag_float(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_drag_float2, vec2, _imgui_drag_float2(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit3, vec3, _imgui_color_edit3(self, imgui, value)); -IMGUI_ITEM_CHECKBOX_VALUE_FUNCTION(_imgui_checkbox_color_edit4, vec4, _imgui_color_edit4(self, imgui, value)); - -static bool _imgui_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) -{ - value.resize(self.max); - _imgui_item_pre(self, IMGUI_INPUT_TEXT); - bool isActivated = ImGui::InputText(self.label_get().c_str(), value.data(), self.max, self.flags); - _imgui_item_post(self, imgui, IMGUI_INPUT_TEXT, isActivated); - return isActivated; -} - -static bool _imgui_combo(ImguiItem self, Imgui* imgui, s32* value) -{ - std::vector cStrings; - cStrings.reserve(self.items.size()); - for (auto& string : self.items) - cStrings.emplace_back(string.c_str()); - - _imgui_item_pre(self, IMGUI_COMBO); - - bool isActivated = ImGui::Combo(self.label_get().c_str(), value, cStrings.data(), (s32)self.items.size()); - if (_imgui_is_input_default()) - { - *value = self.value; - isActivated = true; - } - - _imgui_item_post(self, imgui, IMGUI_COMBO, isActivated); - - return isActivated; -}; - -IMGUI_ITEM_CUSTOM_FUNCTION(_imgui_atlas_button, IMGUI_ATLAS_BUTTON, -{ - ImVec2 size = _imgui_item_size_get(self, type); - - if (self.is_size()) - { - isActivated = ImGui::Button(self.label_get().c_str(), size); - - ImVec2 start = ImGui::GetItemRectMin() + self.atlasOffset; - ImVec2 end = start + ImVec2(ATLAS_SIZE(self.atlas)); - - ImGui::GetWindowDrawList()->AddImage(imgui->resources->atlas.id, start, end, ATLAS_UV_ARGS(self.atlas)); - } - else - isActivated = ImGui::ImageButton(self.label_get().c_str(), imgui->resources->atlas.id, size, ATLAS_UV_ARGS(self.atlas)); -}); - -static bool _imgui_selectable_input_int(const ImguiItem& self, Imgui* imgui, s32& value) -{ - static s32 temp; - static s32 id = ID_NONE; - ImguiItem selectable = self.copy({.label = std::format(IMGUI_SELECTABLE_INPUT_INT_FORMAT, value)}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) - { - isActivated = _imgui_input_int(IMGUI_CHANGE_INPUT_INT.copy({.size = size}), imgui, temp); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) - { - value = temp; - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } - else - { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) - { - temp = value; - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } - - return isActivated; -}; - -static bool _imgui_selectable_input_text(const ImguiItem& self, Imgui* imgui, std::string& value) -{ - static std::string buffer{}; - static s32 id = ID_NONE; - ImguiItem selectable = self.copy({}); - ImVec2 size = _imgui_item_size_get(selectable, IMGUI_SELECTABLE); - bool isActivated = false; - - if (id == self.id) - { - isActivated = _imgui_input_text(IMGUI_CHANGE_INPUT_TEXT.copy({.size = size}), imgui, buffer); - imgui_contextual_actions_disable(imgui); - - if (isActivated || _imgui_is_no_click_on_item()) - { - value = buffer; - buffer.clear(); - id = ID_NONE; - imgui_contextual_actions_enable(imgui); - } - } - else - { - isActivated = _imgui_selectable(selectable, imgui); - - if (_imgui_is_input_begin()) - { - buffer = value; - buffer.resize(IMGUI_CHANGE_INPUT_TEXT.max); - id = self.id; - ImGui::SetKeyboardFocusHere(-1); - } - } - - return isActivated; -}; - -IMGUI_ITEM_ATLAS_FUNCTION(_imgui_atlas_selectable, _imgui_selectable(self, imgui)); -IMGUI_ITEM_ATLAS_VALUE_FUNCTION(_imgui_atlas_selectable_input_int, s32, _imgui_selectable_input_int(self, imgui, value)); -IMGUI_ITEM_ATLAS_VALUE_FUNCTION(_imgui_atlas_selectable_input_text, std::string, _imgui_selectable_input_text(self, imgui, value)); - -static bool _imgui_confirm_popup(ImguiItem self, Imgui* imgui, ImguiPopupState* state = nullptr, bool isOnlyConfirm = false) -{ - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - - if (state) *state = IMGUI_POPUP_STATE_CLOSED; - - if (imgui_begin_popup_modal(self.label_get().c_str(), imgui)) - { - if (state) *state = IMGUI_POPUP_STATE_OPEN; - - ImGui::Text(self.text_get()); - ImGui::Separator(); - - if (_imgui_button(IMGUI_POPUP_OK.copy({.rowCount = isOnlyConfirm ? 1 : IMGUI_CONFIRM_POPUP_ROW_COUNT}), imgui)) - { - imgui_close_current_popup(imgui); - imgui_end_popup(imgui); - if (state) *state = isOnlyConfirm ? IMGUI_POPUP_STATE_CANCEL : IMGUI_POPUP_STATE_CONFIRM; - return true; - } - - ImGui::SameLine(); - - if (!isOnlyConfirm) - { - if (_imgui_button(IMGUI_POPUP_CANCEL, imgui)) - { - imgui_close_current_popup(imgui); - if (state) *state = IMGUI_POPUP_STATE_CANCEL; - } - } - - imgui_end_popup(imgui); - } - - return false; -} - -static void _imgui_no_anm2_path_check(Imgui* self) -{ - if (_imgui_is_window_hovered_and_click_no_anm2_path(self) && !imgui_is_any_popup_open()) - imgui_open_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION.label); - _imgui_confirm_popup(IMGUI_NO_ANM2_PATH_CONFIRMATION, self, nullptr, true); -} - -static void _imgui_context_menu(Imgui* self) -{ - if (!self->isContextualActionsEnabled) return; - - if (_imgui_is_window_hovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) - imgui_open_popup(IMGUI_CONTEXT_MENU.label_get()); - - if (imgui_begin_popup(IMGUI_CONTEXT_MENU.label_get(), self)) - { - _imgui_selectable(IMGUI_CUT, self); - _imgui_selectable(IMGUI_COPY, self); - _imgui_selectable(IMGUI_PASTE.copy({!clipboard_is_value()}), self); - - imgui_end_popup(self); - } -} - -static void _imgui_spritesheet_editor_set(Imgui* self, s32 id) -{ - if (self->anm2->spritesheets.contains(id)) self->editor->spritesheetID = id; -} - -static void _imgui_timeline(Imgui* self) -{ - static const ImU32 frameColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_COLOR); - static const ImU32 frameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_COLOR); - static const ImU32 headerFrameMultipleColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR); - static const ImU32 headerFrameInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR); - static const ImU32 headerFrameMultipleInactiveColor = ImGui::GetColorU32(IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR); - static const ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); - static Anm2Reference hoverReference; - static Anm2Reference swapItemReference; - static Anm2Type& itemType = self->reference->itemType; - static ImVec2 itemMin{}; - static ImVec2 localMousePos{}; - static ImVec2 mousePos{}; - static ImVec2 playheadPos{}; - static ImVec2 scroll{}; - static bool isItemSwap = false; - static const ImVec2& frameSize = IMGUI_TIMELINE_FRAME_SIZE; - static f32& time = self->preview->time; - static s32 frameTime{}; - static s32& itemID = self->reference->itemID; - - IMGUI_BEGIN_OR_RETURN(IMGUI_TIMELINE, self); - _imgui_no_anm2_path_check(self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - if (!animation) - { - ImGui::Text(IMGUI_TIMELINE_ANIMATION_NONE); - _imgui_end(); // IMGUI_TIMELINE - return; - } - - s32 length = animation->frameNum; - s32 actualLength = anm2_animation_length_get(animation); - - ImVec2 actualFramesSize = {actualLength * frameSize.x, frameSize.y}; - ImVec2 framesSize = {length * frameSize.x, frameSize.y}; - - ImVec2 defaultItemSpacing = ImGui::GetStyle().ItemSpacing; - ImVec2 defaultWindowPadding = ImGui::GetStyle().WindowPadding; - ImVec2 defaultFramePadding = ImGui::GetStyle().FramePadding; - - vec2 windowSize = ImGui::GetContentRegionAvail(); - vec2 childSize = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size.y}; - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - - _imgui_begin_child(IMGUI_TIMELINE_CHILD.copy({.size = childSize}), self); - ImVec2 clipRectMin = ImGui::GetWindowDrawList()->GetClipRectMin(); - ImVec2 clipRectMax = ImGui::GetWindowDrawList()->GetClipRectMax(); - clipRectMin.x += IMGUI_TIMELINE_ITEM_SIZE.x; - - ImVec2 scrollDelta{}; - - if (_imgui_is_window_hovered() && !imgui_is_any_popup_open()) - { - ImGuiIO& io = ImGui::GetIO(); - f32 lineHeight = ImGui::GetTextLineHeight(); - - scrollDelta.x -= io.MouseWheelH * lineHeight; - scrollDelta.y -= io.MouseWheel * lineHeight; - } - - std::function timeline_header = [&]() - { - static bool isPlayheadDrag = false; - _imgui_begin_child(IMGUI_TIMELINE_HEADER_CHILD, self); - - ImGui::SetScrollX(scroll.x); - - itemMin = ImGui::GetItemRectMin(); - mousePos = ImGui::GetMousePos(); - localMousePos = ImVec2(mousePos.x - itemMin.x + scroll.x, mousePos.y - itemMin.y); - frameTime = (s32)(localMousePos.x / frameSize.x); - - if (ImGui::IsMouseDown(0) && _imgui_is_window_hovered()) isPlayheadDrag = true; - - if (isPlayheadDrag) - { - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(frameTime, 0, std::max(0, length - 1)); - else - time = std::max(frameTime, 0); - - if (ImGui::IsMouseReleased(0)) - isPlayheadDrag = false; - } - - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - playheadPos = {cursorPos.x + (time * frameSize.x), cursorPos.y}; - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - ImVec2 dummySize = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize; - ImGui::Dummy(dummySize); - - f32 viewWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - s32 start = (s32)std::floor(scroll.x / frameSize.x) - 1; - start = (start < 0) ? 0 : start; - - s32 end = (s32)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - end = (end > ANM2_FRAME_NUM_MAX) ? ANM2_FRAME_NUM_MAX : end; - - playheadPos = ImVec2(cursorPos.x + time * frameSize.x, cursorPos.y); - - for (s32 i = start; i < end; i++) - { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - bool isInactive = i >= length; - - f32 startX = cursorPos.x + i * frameSize.x; - f32 endX = startX + frameSize.x; - ImVec2 positionStart(startX, cursorPos.y); - ImVec2 positionEnd(endX, cursorPos.y + frameSize.y); - - ImU32 bgColor = isInactive - ? (isMultiple ? headerFrameMultipleInactiveColor : headerFrameInactiveColor) - : (isMultiple ? headerFrameMultipleColor : headerFrameColor); - - drawList->AddRectFilled(positionStart, positionEnd, bgColor); - - if (isMultiple) - { - std::string buffer = std::to_string(i); - ImVec2 textSize = ImGui::CalcTextSize(buffer.c_str()); - ImVec2 textPosition(startX + (frameSize.x - textSize.x) * 0.5f, cursorPos.y + (frameSize.y - textSize.y) * 0.5f); - drawList->AddText(textPosition, textColor, buffer.c_str()); - } - - drawList->AddImage(self->resources->atlas.id, positionStart, positionEnd, ATLAS_UV_ARGS(ATLAS_FRAME_ALT)); - } - - _imgui_end_child(); // IMGUI_TIMELINE_HEADER_CHILD - - ImGui::SetNextWindowPos(ImGui::GetWindowPos()); - ImGui::SetNextWindowSize(ImGui::GetWindowSize()); - _imgui_begin(IMGUI_PLAYHEAD, self); - - ImVec2& pos = playheadPos; - - ImVec2 lineStart = {pos.x + (frameSize.x * 0.5f) - (IMGUI_PLAYHEAD_LINE_WIDTH * 0.5f), pos.y + frameSize.y}; - ImVec2 lineEnd = {lineStart.x + IMGUI_PLAYHEAD_LINE_WIDTH, lineStart.y + childSize.y - frameSize.y}; - - drawList = ImGui::GetWindowDrawList(); - - drawList->PushClipRect(clipRectMin, clipRectMax, true); - drawList->AddImage(self->resources->atlas.id, pos, ImVec2(pos.x + frameSize.x, pos.y + frameSize.y), ATLAS_UV_ARGS(ATLAS_PICKER)); - drawList->AddRectFilled(lineStart, lineEnd, IMGUI_PLAYHEAD_LINE_COLOR); - drawList->PopClipRect(); - - _imgui_end(); // IMGUI_PLAYHEAD - }; - - std::function timeline_item_child = [&](Anm2Reference reference, s32& index) - { - Anm2Item* item = anm2_item_from_reference(self->anm2, &reference); - Anm2Type& type = reference.itemType; - if (!item) return; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) return; - - ImVec2 buttonSize = ImVec2(ATLAS_SIZE_NORMAL) + (defaultFramePadding * ImVec2(2, 2)); - - Anm2Layer* layer = nullptr; - Anm2Null* null = nullptr; - s32 buttonCount = type == ANM2_NULL ? 2 : 1; - f32 buttonAreaWidth = buttonCount * buttonSize.x + (buttonCount - 1) * defaultItemSpacing.x; - bool isSelected = (self->reference->itemID == reference.itemID && self->reference->itemType == type); - - ImGui::PushID(reference.itemID); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - ImVec2 childPos = ImGui::GetCursorScreenPos(); - _imgui_begin_child(*IMGUI_TIMELINE_ITEM_CHILDS[type], self); - ImVec2 childSize = ImGui::GetContentRegionAvail(); - - std::string dragDrop = IMGUI_TIMELINE_ITEM_SELECTABLES[type]->dragDrop; - - switch (type) - { - case ANM2_ROOT: - case ANM2_TRIGGERS: - if (_imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy({.isSelected = isSelected}), self)) - *self->reference = reference; - break; - case ANM2_LAYER: - layer = &self->anm2->layers[reference.itemID]; - if - ( - _imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy - ({ - .isSelected = isSelected, - .label = std::format(IMGUI_TIMELINE_ITEM_CHILD_FORMAT, reference.itemID, layer->name) - }), - self - ) - ) - *self->reference = reference; - - break; - case ANM2_NULL: - null = &self->anm2->nulls[reference.itemID]; - if - ( - _imgui_atlas_selectable(IMGUI_TIMELINE_ITEM_SELECTABLES[type]->copy - ({ - .isSelected = isSelected, - .label = std::format(IMGUI_TIMELINE_ITEM_CHILD_FORMAT, reference.itemID, null->name) - }), - self) - ) - *self->reference = reference; - break; - default: - break; - } - - if (imgui_begin_popup_modal(IMGUI_POPUP_ITEM_PROPERTIES, self, IMGUI_POPUP_ITEM_PROPERTIES_SIZE)) - { - static s32 selectedLayerID = ID_NONE; - static s32 selectedNullID = ID_NONE; - Anm2Type& type = reference.itemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER.copy({true}), self, (s32&)type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL.copy({true}), self, (s32&)type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) - { - case ANM2_LAYER: - default: - { - for (auto & [id, layer] : self->anm2->layers) - { - if (id == reference.itemID) continue; - - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - if (_imgui_atlas_selectable(layerItem, self)) selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: - { - for (auto & [id, null] : self->anm2->nulls) - { - if (id == reference.itemID) continue; - - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); - if (_imgui_atlas_selectable(nullItem, self)) selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || - (type == ANM2_LAYER && selectedLayerID == ID_NONE) || - (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({isDisabled}), self)) - { - switch (type) - { - case ANM2_LAYER: - if (!map_find(animation->layerAnimations, selectedLayerID)) - { - anm2_animation_layer_animation_add(animation, selectedLayerID); - anm2_animation_layer_animation_remove(animation, reference.itemID); - } - else - map_swap(animation->layerAnimations, selectedLayerID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - break; - case ANM2_NULL: - if (!map_find(animation->nullAnimations, selectedNullID)) - { - anm2_animation_null_animation_add(animation, selectedNullID); - anm2_animation_null_animation_remove(animation, reference.itemID); - - } - else - map_swap(animation->nullAnimations, selectedNullID, reference.itemID); - - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - break; - default: break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None) && !dragDrop.empty()) - { - *self->reference = reference; - - ImGui::SetDragDropPayload(dragDrop.c_str(), &reference, sizeof(Anm2Reference)); - timeline_item_child(reference, index); - ImGui::EndDragDropSource(); - } - ImGui::PopStyleVar(); - - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(dragDrop.c_str())) - { - Anm2Reference checkReference = *(Anm2Reference*)payload->Data; - if (checkReference != reference) - { - swapItemReference = reference; - isItemSwap = true; - } - } - - ImGui::EndDragDropTarget(); - } - - ImGui::SetCursorScreenPos({childPos.x + childSize.x - buttonAreaWidth, childPos.y + defaultWindowPadding.y}); - - if (type == ANM2_NULL) - { - const ImguiItem& rectItem = null->isShowRect ? IMGUI_TIMELINE_ITEM_SHOW_RECT : IMGUI_TIMELINE_ITEM_HIDE_RECT; - if (_imgui_atlas_button(rectItem, self)) null->isShowRect = !null->isShowRect; - ImGui::SameLine(0.0f, defaultItemSpacing.x); - } - - const ImguiItem& visibleItem = item->isVisible ? IMGUI_TIMELINE_ITEM_VISIBLE : IMGUI_TIMELINE_ITEM_INVISIBLE; - if (_imgui_atlas_button(visibleItem, self)) item->isVisible = !item->isVisible; - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // itemChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_items_child = [&]() - { - static s32& animationID = self->reference->animationID; - s32 index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_ITEMS_CHILD, self); - ImGui::SetScrollY(scroll.y); - - timeline_item_child({animationID, ANM2_ROOT}, index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_child({animationID, ANM2_LAYER, id}, index); - - for (auto & [id, null] : animation->nullAnimations) - timeline_item_child({animationID, ANM2_NULL, id}, index); - - timeline_item_child({animationID, ANM2_TRIGGERS}, index); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEMS_CHILD - - if (isItemSwap) - { - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - imgui_snapshot(self, IMGUI_ACTION_ITEM_SWAP); - - switch (swapItemReference.itemType) - { - case ANM2_LAYER: - vector_value_swap(animation->layerOrder, self->reference->itemID, swapItemReference.itemID); - break; - case ANM2_NULL: - map_swap(animation->nullAnimations, self->reference->itemID, swapItemReference.itemID); - break; - default: break; - } - - self->reference->itemID = swapItemReference.itemID; - anm2_reference_clear(&swapItemReference); - isItemSwap = false; - } - }; - - std::function timeline_item_frames = [&](Anm2Reference reference, s32& index) - { - Anm2Item* item = anm2_item_from_reference(self->anm2, &reference); - if (!item) return; - Anm2Type& type = reference.itemType; - if (!self->settings->timelineIsShowUnused && item->frames.empty() && (type == ANM2_LAYER || type == ANM2_NULL)) return; - - ImGui::PushID(index); - - ImDrawList* drawList = ImGui::GetWindowDrawList(); - - f32 viewWidth = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FRAMES_CHILD.copy({.size = actualFramesSize.x > framesSize.x ? actualFramesSize : framesSize}), self); - - ImVec2 startPos = ImGui::GetCursorPos(); - ImVec2 cursorPos = ImGui::GetCursorScreenPos(); - - if (_imgui_is_window_hovered()) - { - hoverReference = reference; - hoverReference.time = frameTime; - hoverReference.frameIndex = anm2_frame_index_from_time(self->anm2, reference, frameTime); - self->clipboard->location = hoverReference; - self->clipboard->type = CLIPBOARD_FRAME; - - if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) - { - *self->reference = reference; - if (reference.itemType == ANM2_LAYER && reference.itemID != ID_NONE) - _imgui_spritesheet_editor_set(self, self->anm2->layers[self->reference->itemID].spritesheetID); - } - } - - s32 start = (s32)std::floor(scroll.x / frameSize.x) - 1; - if (start < 0) start = 0; - - s32 end = (s32)std::ceil((scroll.x + viewWidth) / frameSize.x) + 1; - if (end > ANM2_FRAME_NUM_MAX) end = ANM2_FRAME_NUM_MAX; - - for (s32 i = start; i < end; i++) - { - bool isMultiple = (i % IMGUI_TIMELINE_FRAME_MULTIPLE) == 0; - ImU32 bgColor = isMultiple ? frameMultipleColor : frameColor; - - f32 startX = cursorPos.x + i * frameSize.x; - f32 endX = startX + frameSize.x; - ImVec2 startPosition(startX, cursorPos.y); - ImVec2 endPosition(endX, cursorPos.y + frameSize.y); - - drawList->AddRectFilled(startPosition, endPosition, bgColor); - drawList->AddImage(self->resources->atlas.id, startPosition, endPosition, ATLAS_UV_ARGS(ATLAS_FRAME)); - } - - ImGui::SetCursorPos(startPos); - - std::function timeline_item_frame = [&](s32 i, Anm2Frame& frame) - { - static s32 frameDelayStart{}; - static f32 frameDelayTimeStart{}; - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - static bool isFrameSwap = false; - static bool isDrag = false; - - ImGui::PushID(i); - reference.frameIndex = i; - ImVec2 framePos = ImGui::GetCursorPos(); - AtlasType atlas = frame.isInterpolated ? ATLAS_CIRCLE : ATLAS_SQUARE; - - if (type == ANM2_TRIGGERS) - { - framePos.x = startPos.x + (frameSize.x * frame.atFrame); - atlas = ATLAS_TRIGGER; - } - - ImguiItem frameButton = IMGUI_TIMELINE_FRAMES[type]->copy - ({.isSelected = reference == *self->reference, .size = {frameSize.x * frame.delay, frameSize.y}, .id = i, .atlas = atlas}); - - ImGui::SetCursorPos(framePos); - - if (_imgui_atlas_button(frameButton, self)) - { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceNoDisableHover)) - { - if (!isDrag) - { - *self->reference = reference; - frameDelayStart = frame.delay; - frameDelayTimeStart = frameTime; - isFrameSwap = false; - isDrag = true; - } - - ImGui::SetDragDropPayload(frameButton.drag_drop_get(), &reference, sizeof(Anm2Reference)); - if (!isModCtrl) timeline_item_frame(i, frame); - ImGui::EndDragDropSource(); - } - - if (isDrag) - { - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, self->reference)) - { - switch (self->reference->itemType) - { - case ANM2_TRIGGERS: - { - referenceFrame->atFrame = std::max(frameTime, 0); - for (auto& trigger : animation->triggers.frames) - { - if (&trigger == referenceFrame) continue; - if (trigger.atFrame == referenceFrame->atFrame) - { - referenceFrame->atFrame++; - break; - } - } - break; - } - case ANM2_ROOT: - case ANM2_LAYER: - case ANM2_NULL: - { - if (isModCtrl) - referenceFrame->delay = std::max(frameDelayStart + (s32)(frameTime - frameDelayTimeStart), ANM2_FRAME_NUM_MIN); - break; - } - default: break; - } - } - } - - if (ImGui::BeginDragDropTarget()) - { - ImGui::AcceptDragDropPayload(frameButton.drag_drop_get()); - ImGui::EndDragDropTarget(); - } - - if (isDrag && ImGui::IsMouseReleased(0)) - { - if - ( !isFrameSwap && - *self->reference != hoverReference && - self->reference->itemType == hoverReference.itemType - ) - { - imgui_snapshot(self, IMGUI_ACTION_FRAME_MOVE); - if (Anm2Frame* referenceFrame = anm2_frame_from_reference(self->anm2, self->reference)) - { - Anm2Reference addReference = hoverReference; - addReference.frameIndex = hoverReference.frameIndex < self->reference->frameIndex ? - std::min(0, addReference.frameIndex - 2) : - std::min(0, addReference.frameIndex - 1); - Anm2Frame addFrame = *referenceFrame; - anm2_frame_remove(self->anm2, self->reference); - anm2_frame_add(self->anm2, &addFrame, &hoverReference); - *self->reference = hoverReference; - hoverReference = Anm2Reference(); - } - } - - isDrag = false; - } - - - if (i < (s32)item->frames.size() - 1) ImGui::SameLine(); - - ImGui::PopID(); - }; - - for (auto [i, frame] : std::views::enumerate(item->frames)) - timeline_item_frame(i, frame); - - _imgui_end_child(); // itemFramesChild - - ImGui::PopID(); - - index++; - }; - - std::function timeline_frames_child = [&]() - { - s32& animationID = self->reference->animationID; - s32 index = 0; - - _imgui_begin_child(IMGUI_TIMELINE_FRAMES_CHILD, self); - scroll.x = ImGui::GetScrollX() + scrollDelta.x; - scroll.y = ImGui::GetScrollY() + scrollDelta.y; - ImGui::SetScrollX(scroll.x); - ImGui::SetScrollY(scroll.y); - - timeline_item_frames(Anm2Reference(animationID, ANM2_ROOT), index); - - for (auto& id : std::ranges::reverse_view(animation->layerOrder)) - timeline_item_frames(Anm2Reference(animationID, ANM2_LAYER, id), index); - - for (auto & [id, null] : animation->nullAnimations) - timeline_item_frames(Anm2Reference(animationID, ANM2_NULL, id), index); - - timeline_item_frames(Anm2Reference(animationID, ANM2_TRIGGERS), index); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - _imgui_context_menu(self); - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_FRAMES_CHILD - }; - - // In order to set scroll properly timeline_frames_child must be called first - ImGui::SetCursorPos(ImVec2(IMGUI_TIMELINE_ITEM_SIZE)); - timeline_frames_child(); - ImGui::SetCursorPos(ImVec2()); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, defaultItemSpacing); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, defaultWindowPadding); - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_CHILD, self); - - const ImguiItem& unusedItem = self->settings->timelineIsShowUnused ? IMGUI_TIMELINE_SHOW_UNUSED : IMGUI_TIMELINE_HIDE_UNUSED; - if (_imgui_atlas_button(unusedItem, self)) self->settings->timelineIsShowUnused = !self->settings->timelineIsShowUnused; - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_CHILD - ImGui::SameLine(); - timeline_header(); - - timeline_items_child(); - - ImGui::PopStyleVar(2); - - _imgui_end_child(); // IMGUI_TIMELINE_CHILD - - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); - _imgui_begin_child(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, self); - - _imgui_button(IMGUI_TIMELINE_ADD_ITEM, self); - - if (imgui_begin_popup_modal(IMGUI_TIMELINE_ADD_ITEM.popup, self, IMGUI_TIMELINE_ADD_ITEM.popupSize)) - { - static s32 selectedLayerID = ID_NONE; - static s32 selectedNullID = ID_NONE; - s32& type = self->settings->timelineAddItemType; - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, self); - - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, self, type); - _imgui_radio_button(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, self, type); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, self); - - switch (type) - { - case ANM2_LAYER: - default: - { - for (auto & [id, layer] : self->anm2->layers) - { - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - if (_imgui_atlas_selectable(layerItem, self)) selectedLayerID = id; - - ImGui::PopID(); - }; - break; - } - case ANM2_NULL: - { - for (auto & [id, null] : self->anm2->nulls) - { - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); - if (_imgui_atlas_selectable(nullItem, self)) selectedNullID = id; - - ImGui::PopID(); - }; - break; - } - } - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD - - _imgui_begin_child(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, self); - - if (self->anm2->layers.size() == 0) selectedLayerID = ID_NONE; - if (self->anm2->nulls.size() == 0) selectedNullID = ID_NONE; - - bool isDisabled = type == ANM2_NONE || - (type == ANM2_LAYER && selectedLayerID == ID_NONE) || - (type == ANM2_NULL && selectedNullID == ID_NONE); - - if (_imgui_button(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM.copy({isDisabled}), self)) - { - switch (type) - { - case ANM2_LAYER: - anm2_animation_layer_animation_add(animation, selectedLayerID); - *self->reference = {self->reference->animationID, ANM2_LAYER, selectedLayerID}; - break; - case ANM2_NULL: - anm2_animation_null_animation_add(animation, selectedNullID); - *self->reference = {self->reference->animationID, ANM2_NULL, selectedNullID}; - break; - default: break; - } - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_TIMELINE_REMOVE_ITEM.copy({!item || itemType == ANM2_ROOT || itemType == ANM2_TRIGGERS}), self)) - { - switch (itemType) - { - case ANM2_LAYER: anm2_animation_layer_animation_remove(animation, itemID); break; - case ANM2_NULL: anm2_animation_null_animation_remove(animation, itemID); break; - default: break; - } - - anm2_reference_item_clear(self->reference); - } - - _imgui_end_child(); //IMGUI_TIMELINE_FOOTER_ITEM_CHILD - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - ImGui::SameLine(); - ImGui::PopStyleVar(); - - _imgui_begin_child(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, self); - - if (_imgui_button(self->preview->isPlaying ? IMGUI_PAUSE : IMGUI_PLAY, self)) - { - if (!self->preview->isPlaying && time >= animation->frameNum - 1) - time = 0.0f; - self->preview->isPlaying = !self->preview->isPlaying; - } - - if (_imgui_button(IMGUI_ADD_FRAME.copy({!item}), self)) - { - Anm2Reference frameReference = *self->reference; - frameReference.frameIndex = item->frames.empty() ? 0 : std::clamp(frameReference.frameIndex, 0, (s32)(item->frames.size() - 1)); - Anm2Frame* addFrame = anm2_frame_from_reference(self->anm2, &frameReference); - anm2_frame_add(self->anm2, addFrame, &frameReference); - } - - if(_imgui_button(IMGUI_REMOVE_FRAME.copy({!frame}), self)) - { - anm2_frame_remove(self->anm2, self->reference); - anm2_reference_frame_clear(self->reference); - } - - _imgui_button(IMGUI_BAKE.copy({!frame || itemType == ANM2_TRIGGERS}), self); - - if (imgui_begin_popup_modal(IMGUI_BAKE.popup, self, IMGUI_BAKE.popupSize)) - { - static s32& interval = self->settings->bakeInterval; - static bool& isRoundScale = self->settings->bakeIsRoundScale; - static bool& isRoundRotation = self->settings->bakeIsRoundRotation; - - _imgui_begin_child(IMGUI_BAKE_CHILD, self); - - _imgui_input_int(IMGUI_BAKE_INTERVAL.copy({.max = frame->delay}), self, interval); - _imgui_checkbox(IMGUI_BAKE_ROUND_SCALE, self, isRoundScale); - _imgui_checkbox(IMGUI_BAKE_ROUND_ROTATION, self, isRoundRotation); - - if (_imgui_button(IMGUI_BAKE_CONFIRM, self)) - { - anm2_frame_bake(self->anm2, self->reference, interval, isRoundScale, isRoundRotation); - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - - _imgui_end_child(); //IMGUI_BAKE_CHILD) - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_FIT_ANIMATION_LENGTH, self)) anm2_animation_length_set(animation); - - _imgui_input_int(IMGUI_ANIMATION_LENGTH, self, animation->frameNum); - _imgui_input_int(IMGUI_FPS, self, self->anm2->fps); - _imgui_checkbox(IMGUI_LOOP, self, animation->isLoop); - _imgui_selectable_input_text(IMGUI_CREATED_BY.copy({.label = self->anm2->createdBy}), self, self->anm2->createdBy); - - _imgui_end_child(); // IMGUI_TIMELINE_FOOTER_OPTIONS_CHILD - - _imgui_end(); // IMGUI_TIMELINE -} - -static void _imgui_onionskin(Imgui* self) -{ - IMGUI_BEGIN_OR_RETURN(IMGUI_ONIONSKIN, self); - - static auto& isEnabled = self->settings->onionskinIsEnabled; - static auto& beforeCount = self->settings->onionskinBeforeCount; - static auto& afterCount = self->settings->onionskinAfterCount; - static auto& beforeColorOffset = self->settings->onionskinBeforeColorOffset; - static auto& afterColorOffset = self->settings->onionskinAfterColorOffset; - static auto& drawOrder = self->settings->onionskinDrawOrder; - - _imgui_checkbox(IMGUI_ONIONSKIN_ENABLED, self, isEnabled); - - auto onionskin_section = [&](auto& text, auto& count, auto& colorOffset) - { - ImGui::PushID(text.label.c_str()); - _imgui_text(text, self); - _imgui_input_int(IMGUI_ONIONSKIN_COUNT.copy({!isEnabled}), self, count); - _imgui_color_edit3(IMGUI_ONIONSKIN_COLOR_OFFSET.copy({!isEnabled}), self, colorOffset); - ImGui::PopID(); - }; - - onionskin_section(IMGUI_ONIONSKIN_BEFORE, beforeCount, beforeColorOffset); - onionskin_section(IMGUI_ONIONSKIN_AFTER, afterCount, afterColorOffset); - - ImGui::Separator(); - - _imgui_text(IMGUI_ONIONSKIN_DRAW_ORDER, self); - _imgui_radio_button(IMGUI_ONIONSKIN_BELOW.copy({!isEnabled}), self, drawOrder); - _imgui_radio_button(IMGUI_ONIONSKIN_ABOVE.copy({!isEnabled}), self, drawOrder); - - _imgui_end(); // IMGUI_ONIONSKIN -} - -static void _imgui_taskbar(Imgui* self) -{ - static ImguiPopupState exitConfirmState = IMGUI_POPUP_STATE_CLOSED; - - ImGuiViewport* viewport = ImGui::GetMainViewport(); - ImguiItem taskbar = IMGUI_TASKBAR; - ImGui::SetNextWindowSize({viewport->Size.x, IMGUI_TASKBAR.size.y}); - ImGui::SetNextWindowPos(viewport->Pos); - _imgui_begin(taskbar, self); - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - Anm2Item* item = anm2_item_from_reference(self->anm2, self->reference); - - _imgui_selectable(IMGUI_FILE, self); - - if (imgui_begin_popup(IMGUI_FILE.popup, self)) - { - _imgui_selectable(IMGUI_NEW, self); - _imgui_selectable(IMGUI_OPEN, self); - _imgui_selectable(IMGUI_SAVE.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_SAVE_AS.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXPLORE_ANM2_LOCATION.copy({self->anm2->path.empty()}), self); - _imgui_selectable(IMGUI_EXIT, self); - imgui_end_popup(self); - } - - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_OPEN) - { - _imgui_anm2_open(self, self->dialog->path); - dialog_reset(self->dialog); - } - - if (self->dialog->isSelected && self->dialog->type == DIALOG_ANM2_SAVE) - { - anm2_serialize(self->anm2, self->dialog->path); - window_title_from_path_set(self->window, self->dialog->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->dialog->path)); - dialog_reset(self->dialog); - } - - if (self->isTryQuit) imgui_open_popup(IMGUI_EXIT_CONFIRMATION.label); - - _imgui_confirm_popup(IMGUI_EXIT_CONFIRMATION, self, &exitConfirmState); - - switch (exitConfirmState) - { - case IMGUI_POPUP_STATE_CONFIRM: self->isQuit = true; break; - case IMGUI_POPUP_STATE_CANCEL: self->isTryQuit = false; break; - default: break; - } - - _imgui_selectable(IMGUI_WIZARD.copy({}), self); - - if (imgui_begin_popup(IMGUI_WIZARD.popup, self)) - { - _imgui_selectable(IMGUI_GENERATE_ANIMATION_FROM_GRID.copy({!item || (self->reference->itemType != ANM2_LAYER)}), self); - _imgui_selectable(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.copy({!item}), self); - _imgui_selectable(IMGUI_SCALE_ANM2.copy({self->anm2->animations.empty()}), self); - _imgui_selectable(IMGUI_RENDER_ANIMATION.copy({!animation}), self); - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_GENERATE_ANIMATION_FROM_GRID.popup, self, IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize)) - { - static auto& startPosition = self->settings->generateStartPosition; - static auto& size = self->settings->generateSize; - static auto& pivot = self->settings->generatePivot; - static auto& rows = self->settings->generateRows; - static auto& columns = self->settings->generateColumns; - static auto& count = self->settings->generateCount; - static auto& delay = self->settings->generateDelay; - static f32& time = self->generatePreview->time; - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, self); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, self, startPosition); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, self, size); - _imgui_input_int2(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, self, pivot); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, self, rows); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, self, columns); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT.copy({.max = rows * columns}), self, count); - _imgui_input_int(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, self, delay); - _imgui_end_child(); //IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, self); - - generate_preview_draw(self->generatePreview); - ImGui::Image(self->generatePreview->canvas.framebuffer, GENERATE_PREVIEW_SIZE); - - _imgui_begin_child(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, self); - _imgui_slider_float(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, self, time); - _imgui_end_child(); // IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD - - _imgui_end_child(); //IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, self)) - { - anm2_generate_from_grid(self->anm2, self->reference, startPosition, size, pivot, columns, count, delay); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popup, self, IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize)) - { - static auto& isCrop = self->settings->changeIsCrop; - static auto& isSize = self->settings->changeIsSize; - static auto& isPosition = self->settings->changeIsPosition; - static auto& isPivot = self->settings->changeIsPivot; - static auto& isScale = self->settings->changeIsScale; - static auto& isRotation = self->settings->changeIsRotation; - static auto& isColorOffset = self->settings->changeIsColorOffset; - static auto& isTint = self->settings->changeIsTint; - static auto& isVisibleSet = self->settings->changeIsVisibleSet; - static auto& isInterpolatedSet = self->settings->changeIsInterpolatedSet; - static auto& crop = self->settings->changeCrop; - static auto& size = self->settings->changeSize; - static auto& position = self->settings->changePosition; - static auto& pivot = self->settings->changePivot; - static auto& scale = self->settings->changeScale; - static auto& rotation = self->settings->changeRotation; - static auto& isDelay = self->settings->changeIsDelay; - static auto& delay = self->settings->changeDelay; - static auto& tint = self->settings->changeTint; - static auto& colorOffset = self->settings->changeColorOffset; - static auto& isVisible = self->settings->changeIsVisible; - static auto& isInterpolated = self->settings->changeIsInterpolated; - static auto& isFromSelectedFrame = self->settings->changeIsFromSelectedFrame; - static auto& numberFrames = self->settings->changeNumberFrames; - s32 start = std::max(self->reference->frameIndex, 0); - s32 max = isFromSelectedFrame ? - std::max(ANM2_FRAME_NUM_MIN, (s32)item->frames.size() - start) : (s32)item->frames.size(); - - auto change_frames = [&](Anm2ChangeType type) - { - anm2_item_frame_set - ( - self->anm2, self->reference, - Anm2FrameChange - { - isVisibleSet ? std::optional{isVisible} : std::nullopt, - isInterpolatedSet ? std::optional{isInterpolated} : std::nullopt, - isRotation ? std::optional{rotation} : std::nullopt, - isDelay ? std::optional{delay} : std::nullopt, - isCrop ? std::optional{crop} : std::nullopt, - isPivot ? std::optional{pivot} : std::nullopt, - isPosition ? std::optional{position} : std::nullopt, - isSize ? std::optional{size} : std::nullopt, - isScale ? std::optional{scale} : std::nullopt, - isColorOffset ? std::optional{colorOffset} : std::nullopt, - isTint ? std::optional{tint} : std::nullopt - }, - type, start, numberFrames - ); - - imgui_close_current_popup(self); - }; - - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, self); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({!isCrop}), self, crop, isCrop); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({!isSize}), self, size, isSize); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({!isPosition}), self, position, isPosition); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({!isPivot}), self, pivot, isPivot); - _imgui_checkbox_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({!isScale}), self, scale, isScale); - _imgui_checkbox_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({!isRotation}), self, rotation, isRotation); - _imgui_checkbox_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({!isDelay}), self, delay, isDelay); - _imgui_checkbox_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({!isTint}), self, tint, isTint); - _imgui_checkbox_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({!isColorOffset}), self, colorOffset, isColorOffset); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({!isVisibleSet}), self, isVisible, isVisibleSet); - ImGui::NewLine(); - _imgui_checkbox_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({!isInterpolatedSet}), self, isInterpolated, isInterpolatedSet); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - - _imgui_begin_child(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, self); - _imgui_text(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self); - _imgui_checkbox(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, self, isFromSelectedFrame); - _imgui_input_int(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES.copy({.max = max, .value = max}), self, numberFrames); - _imgui_end_child(); // IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, self)) change_frames(ANM2_CHANGE_ADD); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, self)) change_frames(ANM2_CHANGE_SUBTRACT); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, self)) change_frames(ANM2_CHANGE_SET); - if (_imgui_button(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_SCALE_ANM2.popup, self, IMGUI_SCALE_ANM2.popupSize)) - { - _imgui_begin_child(IMGUI_SCALE_ANM2_OPTIONS_CHILD, self); - _imgui_input_float(IMGUI_SCALE_ANM2_VALUE, self, self->settings->scaleValue); - _imgui_end_child(); // IMGUI_SCALE_ANM2_OPTIONS_CHILD - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - if (_imgui_button(IMGUI_SCALE_ANM2_SCALE, self)) - { - anm2_scale(self->anm2, self->settings->scaleValue); - imgui_close_current_popup(self); - } - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_FOOTER_CHILD - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION.popup, self, IMGUI_RENDER_ANIMATION.popupSize)) - { - static DialogType& dialogType = self->dialog->type; - static bool& dialogIsSelected = self->dialog->isSelected; - static s32& type = self->settings->renderType; - static f32& scale = self->settings->renderScale; - static bool& isUseAnimationBounds = self->settings->renderIsUseAnimationBounds; - static std::string& dialogPath = self->dialog->path; - static std::string& ffmpegPath = self->settings->renderFFmpegPath; - static std::string& format = self->settings->renderFormat; - static std::string& path = self->settings->renderPath; - - _imgui_begin_child(IMGUI_RENDER_ANIMATION_CHILD, self); - - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, self)) - dialog_render_path_set(self->dialog, (RenderType)type); - - if (dialogIsSelected && (dialogType == DIALOG_RENDER_PATH_SET)) - { - path = path_extension_change(dialogPath, RENDER_EXTENSIONS[type]); - dialog_reset(self->dialog); - } - - _imgui_input_text(IMGUI_RENDER_ANIMATION_LOCATION, self, path); - - if (_imgui_atlas_button(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, self)) - dialog_ffmpeg_path_set(self->dialog); - - if (dialogIsSelected && dialogType == DIALOG_FFMPEG_PATH_SET) - { - ffmpegPath = self->dialog->path; - dialog_reset(self->dialog); - } - - _imgui_input_text(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, self, ffmpegPath); - _imgui_combo(IMGUI_RENDER_ANIMATION_OUTPUT, self, &type); - _imgui_input_text(IMGUI_RENDER_ANIMATION_FORMAT.copy({type != RENDER_PNG}), self, format); - _imgui_checkbox(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, self, isUseAnimationBounds); - _imgui_input_float(IMGUI_RENDER_ANIMATION_SCALE.copy({!isUseAnimationBounds}), self, scale); - - _imgui_end_child(); // IMGUI_RENDER_ANIMATION_CHILD - - _imgui_begin_child(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_RENDER_ANIMATION_CONFIRM, self)) - { - bool isRenderStart = true; - - if (!std::filesystem::exists(ffmpegPath)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR); - isRenderStart = false; - } - - if (isRenderStart) - { - switch (self->settings->renderType) - { - case RENDER_PNG: - if (!std::filesystem::is_directory(path)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR); - isRenderStart = false; - } - break; - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: - if (!path_is_valid(path)) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR); - isRenderStart = false; - } - default: - break; - } - } - - if (isRenderStart) - preview_render_start(self->preview); - else - self->preview->isRenderCancelled = true; - - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - imgui_close_current_popup(self); - - _imgui_end_child(); // IMGUI_RENDER_ANIMATION_FOOTER_CHILD - - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_RENDER_ANIMATION_CONFIRM.popup, self, IMGUI_RENDER_ANIMATION_CONFIRM.popupSize)) - { - static s32& type = self->settings->renderType; - static std::string& format = self->settings->renderFormat; - - auto rendering_end = [&]() - { - preview_render_end(self->preview); - imgui_close_current_popup(self); - }; - - std::vector& frames = self->preview->renderFrames; - std::string path = std::string(self->settings->renderPath.c_str()); - - if (self->preview->isRenderCancelled) - { - rendering_end(); - self->preview->isRenderCancelled = false; - } - - if (!animation) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR); - rendering_end(); - } - - _imgui_begin_child(IMGUI_RENDERING_ANIMATION_CHILD, self); - - f32 progress = self->preview->time / (animation->frameNum - 1); - ImGui::ProgressBar(progress); - - _imgui_text(IMGUI_RENDERING_ANIMATION_INFO, self); - - _imgui_end_child(); //IMGUI_RENDERING_ANIMATION_CHILD - - if (_imgui_button(IMGUI_RENDERING_ANIMATION_CANCEL, self)) - self->preview->isRenderCancelled = true; - - if (self->preview->isRenderFinished && frames.empty()) - { - imgui_log_push(self, IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR); - rendering_end(); - } - - if (self->preview->isRenderFinished) - { - switch (type) - { - case RENDER_PNG: - { - std::filesystem::path workingPath = std::filesystem::current_path(); - std::filesystem::current_path(path); - - for (auto [i, frame] : std::views::enumerate(frames)) - { - std::string framePath = std::vformat(format, std::make_format_args(i)); - framePath = path_extension_change(framePath, RENDER_EXTENSIONS[type]); - if (!frame.isInvalid) texture_from_gl_write(&frame, framePath); - } - - std::filesystem::current_path(workingPath); - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT, path)); - break; - } - case RENDER_GIF: - case RENDER_WEBM: - case RENDER_MP4: - { - std::string ffmpegPath = std::string(self->settings->renderFFmpegPath.c_str()); - path = path_extension_change(path, RENDER_EXTENSIONS[self->settings->renderType]); - - if (ffmpeg_render(ffmpegPath, path, frames, self->preview->canvas.size, self->anm2->fps, (RenderType)type)) - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT, path)); - else - imgui_log_push(self, std::format(IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR, path)); - break; - } - default: - break; - } - - rendering_end(); - } - - imgui_end_popup(self); - } - - _imgui_selectable(IMGUI_PLAYBACK.copy({}), self); - - if (imgui_begin_popup(IMGUI_PLAYBACK.popup, self, IMGUI_PLAYBACK.popupSize)) - { - _imgui_checkbox_selectable(IMGUI_ALWAYS_LOOP, self, self->settings->playbackIsLoop); - _imgui_checkbox_selectable(IMGUI_CLAMP_PLAYHEAD, self, self->settings->playbackIsClampPlayhead); - imgui_end_popup(self); - } - - _imgui_selectable(IMGUI_SETTINGS.copy({}), self); - - if (imgui_begin_popup(IMGUI_SETTINGS.popup, self, IMGUI_SETTINGS.popupSize)) - { - if (_imgui_checkbox_selectable(IMGUI_VSYNC, self, self->settings->isVsync)) window_vsync_set(self->settings->isVsync); - _imgui_selectable(IMGUI_HOTKEYS, self); - if (_imgui_selectable(IMGUI_DEFAULT_SETTINGS, self)) *self->settings = Settings(); - imgui_end_popup(self); - } - - if (imgui_begin_popup_modal(IMGUI_HOTKEYS.popup, self, IMGUI_HOTKEYS.popupSize)) - { - _imgui_begin_child(IMGUI_HOTKEYS_CHILD, self); - - if (_imgui_begin_table(IMGUI_HOTKEYS_TABLE, self)) - { - static s32 selectedIndex = INDEX_NONE; - - _imgui_table_setup_column(IMGUI_HOTKEYS_FUNCTION); - _imgui_table_setup_column(IMGUI_HOTKEYS_HOTKEY); - _imgui_table_headers_row(); - - for (s32 i = 0; i < HOTKEY_COUNT; i++) - { - if (!SETTINGS_HOTKEY_MEMBERS[i]) continue; - - bool isSelected = selectedIndex == i; - const char* string = HOTKEY_STRINGS[i]; - std::string* settingString = &(self->settings->*SETTINGS_HOTKEY_MEMBERS[i]); - std::string chordString = isSelected ? IMGUI_HOTKEY_CHANGE : *settingString; - - ImGui::PushID(i); - _imgui_table_next_row(); - _imgui_table_set_column_index(0); - ImGui::TextUnformatted(string); - _imgui_table_set_column_index(1); - - if (ImGui::Selectable(chordString.c_str(), isSelected)) selectedIndex = i; - ImGui::PopID(); - - if (isSelected) - { - ImGuiKeyChord chord = IMGUI_CHORD_NONE; - - if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) chord |= ImGuiMod_Ctrl; - if (ImGui::IsKeyDown(ImGuiMod_Shift)) chord |= ImGuiMod_Shift; - if (ImGui::IsKeyDown(ImGuiMod_Alt)) chord |= ImGuiMod_Alt; - if (ImGui::IsKeyDown(ImGuiMod_Super)) chord |= ImGuiMod_Super; - - for (auto& [_, key] : IMGUI_KEY_MAP) - { - if (ImGui::IsKeyPressed(key)) - { - chord |= key; - imgui_hotkey_chord_registry()[i] = chord; - *settingString = imgui_string_from_chord_get(chord); - selectedIndex = INDEX_NONE; - break; - } - } - } - } - - _imgui_end_table(); - } - - _imgui_end_child(); // IMGUI_HOTKEYS_CHILD; - - _imgui_begin_child(IMGUI_HOTKEYS_OPTIONS_CHILD, self); - if (_imgui_button(IMGUI_HOTKEYS_CONFIRM, self)) imgui_close_current_popup(self); - _imgui_end_child(); // IMGUI_HOTKEYS_OPTIONS_CHILD - - imgui_end_popup(self); - } - - _imgui_end(); -} - -static void _imgui_tools(Imgui* self) -{ - ImGuiStyle style = ImGui::GetStyle(); - - IMGUI_BEGIN_OR_RETURN(IMGUI_TOOLS, self); - - f32 availableWidth = ImGui::GetContentRegionAvail().x; - f32 usedWidth = style.FramePadding.x; - - for (s32 i = 0; i < TOOL_COUNT; i++) - { - ImguiItem item = *IMGUI_TOOL_ITEMS[i]; - - if (i > 0 && usedWidth + ImGui::GetItemRectSize().x < availableWidth) - ImGui::SameLine(); - else - usedWidth = 0; - - item.isSelected = self->settings->tool == (ToolType)i; - - switch ((ToolType)i) - { - case TOOL_UNDO: item.isDisabled = self->snapshots->undoStack.is_empty(); break; - case TOOL_REDO: item.isDisabled = self->snapshots->redoStack.is_empty(); break; - default: break; - } - - if (i != TOOL_COLOR) - _imgui_atlas_button(item, self); - else - _imgui_color_edit4(item, self, self->settings->toolColor); - - usedWidth += ImGui::GetItemRectSize().x + style.ItemSpacing.x; - } - - _imgui_end(); // IMGUI_TOOLS -} - -static void _imgui_layers(Imgui* self) -{ - static s32 selectedLayerID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_LAYERS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); - - _imgui_begin_child(IMGUI_LAYERS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); - ImGui::SetScrollX(0.0f); - - for (auto & [id, layer] : self->anm2->layers) - { - ImGui::PushID(id); - - ImguiItem layerItem = IMGUI_LAYER.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .size = {ImGui::GetContentRegionAvail().x - (IMGUI_LAYER_SPRITESHEET_ID.size.x * 2.0f), 0}, - .id = id - }); - if (_imgui_atlas_selectable_input_text(layerItem, self, layer.name)) selectedLayerID = id; - - ImGui::SameLine(); - - ImguiItem spritesheetItem = IMGUI_LAYER_SPRITESHEET_ID.copy - ({ - .isSelected = selectedLayerID == id, - .label = std::format(IMGUI_LAYER_FORMAT, id, layer.name), - .id = id - }); - _imgui_atlas_selectable_input_int(spritesheetItem, self, layer.spritesheetID); - - ImGui::PopID(); - }; - - _imgui_end_child(); // layersChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_LAYER_ADD.copy({self->anm2->path.empty()}), self)) - selectedLayerID = anm2_layer_add(self->anm2); - - if (_imgui_button(IMGUI_LAYER_REMOVE.copy({selectedLayerID == ID_NONE}), self)) - { - anm2_layer_remove(self->anm2, selectedLayerID); - selectedLayerID = ID_NONE; - } - - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_LAYERS -} - -static void _imgui_nulls(Imgui* self) -{ - static s32 selectedNullID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_NULLS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); - - _imgui_begin_child(IMGUI_NULLS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); - - for (auto & [id, null] : self->anm2->nulls) - { - ImGui::PushID(id); - - ImguiItem nullItem = IMGUI_NULL.copy - ({ - .isSelected = selectedNullID == id, - .label = std::format(IMGUI_NULL_FORMAT, id, null.name), - .id = id - }); - - if (_imgui_atlas_selectable_input_text(nullItem, self, null.name)) selectedNullID = id; - - ImGui::PopID(); - }; - - _imgui_end_child(); // nullsChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_NULL_ADD.copy({self->anm2->path.empty()}), self)) - selectedNullID = anm2_null_add(self->anm2); - - if (_imgui_button(IMGUI_NULL_REMOVE.copy({selectedNullID == ID_NONE}), self)) - { - anm2_null_remove(self->anm2, selectedNullID); - selectedNullID = ID_NONE; - } - - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_NULLS -} - -static void _imgui_animations(Imgui* self) -{ - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATIONS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 size = ImGui::GetContentRegionAvail(); - - _imgui_begin_child(IMGUI_ANIMATIONS_CHILD.copy({.size = {size.x, size.y - IMGUI_FOOTER_CHILD.size.y}}), self); - - for (auto & [id, animation] : self->anm2->animations) - { - ImGui::PushID(id); - - ImguiItem animationItem = IMGUI_ANIMATION.copy - ({ - .isSelected = self->reference->animationID == id, - .label = self->anm2->defaultAnimationID == id ? std::format(IMGUI_ANIMATION_DEFAULT_FORMAT, animation.name) : animation.name, - .id = id - }); - - if (_imgui_atlas_selectable_input_text(animationItem, self, animation.name)) - { - self->reference->animationID = id; - anm2_reference_item_clear(self->reference); - } - - if (ImGui::IsItemHovered()) - { - self->clipboard->type = CLIPBOARD_ANIMATION; - self->clipboard->location = (s32)id; - } - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - if (ImGui::IsDragDropActive()) ImGui::SetNextItemWidth(_imgui_item_size_get(animationItem, IMGUI_SELECTABLE).x); - ImGui::SetDragDropPayload(animationItem.drag_drop_get(), &id, sizeof(s32)); - _imgui_atlas_selectable(animationItem, self); - ImGui::EndDragDropSource(); - } - - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(animationItem.drag_drop_get())) - { - s32 sourceID = *(s32*)payload->Data; - if (sourceID != id) - { - imgui_snapshot(self, IMGUI_ACTION_ANIMATION_SWAP); - map_swap(self->anm2->animations, sourceID, id); - } - } - - ImGui::EndDragDropTarget(); - } - - ImGui::PopID(); - }; - - _imgui_context_menu(self); - - _imgui_end_child(); // animationsChild - - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_ANIMATION_ADD.copy({self->anm2->path.empty()}), self)) - { - s32 id = anm2_animation_add(self->anm2); - self->reference->animationID = id; - - if (self->anm2->animations.size() == 1) - self->anm2->defaultAnimationID = id; - } - - if (_imgui_button(IMGUI_ANIMATION_DUPLICATE.copy({!animation}), self)) - self->reference->animationID = anm2_animation_add(self->anm2, animation, self->reference->animationID); - - _imgui_button(IMGUI_ANIMATION_MERGE.copy({!animation}), self); - - if (imgui_begin_popup_modal(IMGUI_ANIMATION_MERGE.popup, self, IMGUI_ANIMATION_MERGE.popupSize)) - { - const bool isModCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isModShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - static bool& isDeleteAnimationsAfter = self->settings->mergeIsDeleteAnimationsAfter; - static s32 lastClickedID = ID_NONE; - static s32& mergeType = self->settings->mergeType; - static size_t lastAnimationCount = 0; - static std::vector animationIDs; - static std::vector sortedIDs; - - if (self->anm2->animations.size() != lastAnimationCount) - { - sortedIDs.clear(); - for (const auto& [id, _] : self->anm2->animations) - sortedIDs.push_back(id); - std::sort(sortedIDs.begin(), sortedIDs.end()); - lastAnimationCount = self->anm2->animations.size(); - } - - _imgui_begin_child(IMGUI_MERGE_ANIMATIONS_CHILD, self); - - for (const auto& [id, animation] : self->anm2->animations) - { - ImGui::PushID(id); - - if - ( - _imgui_atlas_selectable - ( - IMGUI_ANIMATION.copy - ({ - .isSelected = std::find(animationIDs.begin(), animationIDs.end(), id) != animationIDs.end(), - .label = animation.name - }), - self - ) - ) - { - if (isModCtrl) - { - auto it = std::find(animationIDs.begin(), animationIDs.end(), id); - if (it != animationIDs.end()) - animationIDs.erase(it); - else - animationIDs.push_back(id); - - lastClickedID = id; - } - else if (isModShift) - { - auto it1 = std::find(sortedIDs.begin(), sortedIDs.end(), lastClickedID); - auto it2 = std::find(sortedIDs.begin(), sortedIDs.end(), id); - if (it1 != sortedIDs.end() && it2 != sortedIDs.end()) - { - auto begin = std::min(it1, it2); - auto end = std::max(it1, it2); - for (auto it = begin; it <= end; ++it) - { - if (std::find(animationIDs.begin(), animationIDs.end(), *it) == animationIDs.end()) - animationIDs.push_back(*it); - } - } - } - else - { - animationIDs.clear(); - animationIDs.push_back(id); - lastClickedID = id; - } - } - - ImGui::PopID(); - } - - _imgui_end_child(); //IMGUI_MERGE_ANIMATIONS_CHILD - - _imgui_begin_child(IMGUI_MERGE_ON_CONFLICT_CHILD, self); - _imgui_text(IMGUI_MERGE_ON_CONFLICT, self); - _imgui_radio_button(IMGUI_MERGE_APPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_REPLACE_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_PREPEND_FRAMES, self, mergeType); - _imgui_radio_button(IMGUI_MERGE_IGNORE, self, mergeType); - _imgui_end_child(); //IMGUI_MERGE_ON_CONFLICT_CHILD - - _imgui_begin_child(IMGUI_MERGE_OPTIONS_CHILD, self); - - _imgui_checkbox(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, self, isDeleteAnimationsAfter); - - _imgui_end_child(); //IMGUI_MERGE_OPTIONS_CHILD - - if (_imgui_button(IMGUI_MERGE_CONFIRM.copy({animationIDs.empty()}), self)) - { - anm2_animation_merge(self->anm2, self->reference->animationID, animationIDs, (Anm2MergeType)mergeType); - - if (isDeleteAnimationsAfter) - for (s32 id : animationIDs) - if (id != self->reference->animationID) - self->anm2->animations.erase(id); - - animationIDs.clear(); - imgui_close_current_popup(self); - } - - if (_imgui_button(IMGUI_POPUP_CANCEL, self)) - { - animationIDs.clear(); - imgui_close_current_popup(self); - } - - imgui_end_popup(self); - } - - if (_imgui_button(IMGUI_ANIMATION_REMOVE.copy({!animation}), self)) - { - anm2_animation_remove(self->anm2, self->reference->animationID); - anm2_reference_clear(self->reference); - } - - if (_imgui_button(IMGUI_ANIMATION_DEFAULT.copy({!animation}), self)) - self->anm2->defaultAnimationID = self->reference->animationID; - - _imgui_end_child(); // IMGUI_FOOTER_CHILD - _imgui_end(); // IMGUI_ANIMATIONS -} - -static void _imgui_events(Imgui* self) -{ - static s32 selectedID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_EVENTS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 windowSize = ImGui::GetContentRegionAvail(); - - _imgui_begin_child(IMGUI_EVENTS_CHILD.copy({.size = {windowSize.x, windowSize.y - IMGUI_FOOTER_CHILD.size.y}}), self); - - std::function event_item = [&](s32 id, Anm2Event& event) - { - ImGui::PushID(id); - - if (_imgui_atlas_selectable_input_text(IMGUI_EVENT.copy({.isSelected = id == selectedID, .label = event.name, .id = id}), self, event.name)) - selectedID = id; - - ImGui::PopID(); - }; - - for (auto& [id, event] : self->anm2->events) - event_item(id, event); - - _imgui_end_child(); // eventsChild - - _imgui_begin_child(IMGUI_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_EVENTS_ADD.copy({self->anm2->path.empty()}), self)) - { - s32 id = map_next_id_get(self->anm2->events); - self->anm2->events[id] = Anm2Event{}; - selectedID = id; - } - - if (_imgui_button(IMGUI_EVENTS_REMOVE_UNUSED.copy({self->anm2->events.empty()}), self)) - { - std::unordered_set usedEventIDs; - - for (auto& [id, animation] : self->anm2->animations) - for (auto& trigger : animation.triggers.frames) - if (trigger.eventID != ID_NONE) - usedEventIDs.insert(trigger.eventID); - - for (auto it = self->anm2->events.begin(); it != self->anm2->events.end(); ) - { - if (!usedEventIDs.count(it->first)) - it = self->anm2->events.erase(it); - else - it++; - } - } - - _imgui_end_child(); // IMGUI_ANIMATIONS_OPTIONS_CHILD) - _imgui_end(); // IMGUI_EVENTS -} - -static void _imgui_spritesheets(Imgui* self) -{ - static std::unordered_set selectedIDs; - static s32 highlightedID = ID_NONE; - - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEETS, self); - _imgui_no_anm2_path_check(self); - - ImVec2 windowSize = ImGui::GetContentRegionAvail(); - - _imgui_begin_child(IMGUI_SPRITESHEETS_CHILD.copy({.size = {windowSize.x, windowSize.y - IMGUI_SPRITESHEETS_FOOTER_CHILD.size.y}}), self); - - std::function spritesheet_item = [&](s32 id, Anm2Spritesheet& spritesheet) - { - ImGui::PushID(id); - - Texture& texture = spritesheet.texture; - bool isContains = selectedIDs.contains(id); - - _imgui_begin_child(IMGUI_SPRITESHEET_CHILD, self); - - if (_imgui_checkbox(IMGUI_SPRITESHEET_SELECTED, self, isContains)) - { - if (isContains) - selectedIDs.insert(id); - else - selectedIDs.erase(id); - } - - if (_imgui_atlas_selectable(IMGUI_SPRITESHEET.copy({.isSelected = id == highlightedID, .label = std::format(IMGUI_SPRITESHEET_FORMAT, id, spritesheet.path)}), self)) - highlightedID = id; - - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - ImGui::SetDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get(), &id, sizeof(s32)); - spritesheet_item(id, spritesheet); - ImGui::EndDragDropSource(); - } - - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_SPRITESHEET.drag_drop_get())) - { - s32 sourceID = *(s32*)payload->Data; - if (sourceID != id) - map_swap(self->anm2->spritesheets, sourceID, id); - } - ImGui::EndDragDropTarget(); - } - - ImVec2 spritesheetPreviewSize = IMGUI_SPRITESHEET_PREVIEW_SIZE; - f32 spritesheetAspect = (f32)texture.size.x / texture.size.y; - - if ((IMGUI_SPRITESHEET_PREVIEW_SIZE.x / IMGUI_SPRITESHEET_PREVIEW_SIZE.y) > spritesheetAspect) - spritesheetPreviewSize.x = IMGUI_SPRITESHEET_PREVIEW_SIZE.y * spritesheetAspect; - else - spritesheetPreviewSize.y = IMGUI_SPRITESHEET_PREVIEW_SIZE.x / spritesheetAspect; - - if (texture.isInvalid) - _imgui_atlas(ATLAS_NONE, self); - else - ImGui::Image(texture.id, spritesheetPreviewSize); - - _imgui_end_child(); // IMGUI_SPRITESHEET_CHILD - - ImGui::PopID(); - }; - - for (auto& [id, spritesheet] : self->anm2->spritesheets) - spritesheet_item(id, spritesheet); - - _imgui_end_child(); // spritesheetsChild - - _imgui_begin_child(IMGUI_SPRITESHEETS_FOOTER_CHILD, self); - - if (_imgui_button(IMGUI_SPRITESHEET_ADD.copy({self->anm2->path.empty()}), self)) - dialog_spritesheet_add(self->dialog); - - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_ADD) - { - _imgui_spritesheet_add(self, self->dialog->path); - dialog_reset(self->dialog); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_RELOAD.copy({selectedIDs.empty()}), self)) - { - for (auto& id : selectedIDs) - { - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(self->anm2->path); - Texture texture; - texture_from_path_init(&texture, self->anm2->spritesheets[id].path); - self->anm2->spritesheets[id].texture = texture; - std::filesystem::current_path(workingPath); - } - - imgui_log_push(self, IMGUI_LOG_RELOAD_SPRITESHEET); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_REPLACE.copy({highlightedID == ID_NONE}), self)) - dialog_spritesheet_replace(self->dialog, highlightedID); - - if (self->dialog->isSelected && self->dialog->type == DIALOG_SPRITESHEET_REPLACE) - { - imgui_snapshot(self, IMGUI_ACTION_REPLACE_SPRITESHEET); - - std::filesystem::path workingPath = std::filesystem::current_path(); - std::string anm2WorkingPath = working_directory_from_file_set(self->anm2->path); - std::string spritesheetPath = std::filesystem::relative(self->dialog->path, anm2WorkingPath).string(); - - self->anm2->spritesheets[self->dialog->replaceID].path = spritesheetPath; - Texture texture; - texture_from_path_init(&texture, spritesheetPath); - self->anm2->spritesheets[self->dialog->replaceID].texture = texture; - dialog_reset(self->dialog); - std::filesystem::current_path(workingPath); - } - - if (_imgui_button(IMGUI_SPRITESHEETS_REMOVE_UNUSED.copy({self->anm2->spritesheets.empty()}), self)) - { - std::unordered_set usedSpritesheetIDs; - - for (auto& [layerID, layer] : self->anm2->layers) - if (layer.spritesheetID != ID_NONE) - usedSpritesheetIDs.insert(layer.spritesheetID); - - for (auto it = self->anm2->spritesheets.begin(); it != self->anm2->spritesheets.end(); ) - { - if (!usedSpritesheetIDs.count(it->first)) - { - texture_free(&self->anm2->spritesheets[it->first].texture); - it = self->anm2->spritesheets.erase(it); - } - else - it++; - } - } - - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_ALL.copy({selectedIDs.size() == self->anm2->spritesheets.size()}), self)) - for (auto [id, _] : self->anm2->spritesheets) - selectedIDs.insert(id); - - if (_imgui_button(IMGUI_SPRITESHEETS_SELECT_NONE.copy({selectedIDs.empty()}), self)) - selectedIDs.clear(); - - if (_imgui_button(IMGUI_SPRITESHEET_SAVE.copy({selectedIDs.empty()}), self)) - { - for (auto& id : selectedIDs) - { - Anm2Spritesheet& spritesheet = self->anm2->spritesheets[id]; - std::filesystem::path workingPath = std::filesystem::current_path(); - working_directory_from_file_set(self->anm2->path); - texture_from_gl_write(&spritesheet.texture, spritesheet.path); - imgui_log_push(self, std::format(IMGUI_LOG_SPRITESHEET_SAVE_FORMAT, id, spritesheet.path)); - std::filesystem::current_path(workingPath); - } - } - - if (_imgui_is_no_click_on_item()) highlightedID = ID_NONE; - - _imgui_end_child(); //IMGUI_SPRITESHEETS_FOOTER_CHILD - _imgui_end(); // IMGUI_SPRITESHEETS -} - -static void _imgui_animation_preview(Imgui* self) -{ - static s32& tool = self->settings->tool; - static f32& zoom = self->settings->previewZoom; - static vec2& pan = self->settings->previewPan; - static ivec2& size = self->preview->canvas.size; - static vec2 mousePos{}; - static vec2 previewPos{}; - - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (s32)mousePos.x, (s32)mousePos.y); - - IMGUI_BEGIN_OR_RETURN(IMGUI_ANIMATION_PREVIEW, self); - - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->previewIsGrid); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->previewGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, self->settings->previewGridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, self->settings->previewGridOffset); - _imgui_end_child(); // IMGUI_CANVAS_GRID_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2(); - if (_imgui_button(IMGUI_ANIMATION_PREVIEW_FIT.copy({self->reference->animationID == ID_NONE}), self)) - { - vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform); - - if (rect != vec4(-1.0f) && (rect.z > 0 && rect.w > 0)) - { - f32 scaleX = self->preview->canvas.size.x / rect.z; - f32 scaleY = self->preview->canvas.size.y / rect.w; - f32 fitScale = std::min(scaleX, scaleY); - - zoom = UNIT_TO_PERCENT(fitScale); - - vec2 rectCenter = { rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f }; - pan = -rectCenter * fitScale; - } - } - ImGui::Text(mousePositionString.c_str()); - _imgui_end_child(); //IMGUI_CANVAS_VIEW_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->previewBackgroundColor); - - std::vector animationIDs; - ImguiItem animationOverlayItem = IMGUI_CANVAS_ANIMATION_OVERLAY; - - animationIDs.emplace_back(ID_NONE); - animationOverlayItem.items.emplace_back(IMGUI_NONE); - - for (auto& [id, animation] : self->anm2->animations) - { - animationIDs.emplace_back(id); - animationOverlayItem.items.emplace_back(animation.name); - } - - s32 animationIndex = 0; - - if (self->preview->animationOverlayID != ID_NONE) - animationIndex = std::find(animationIDs.begin(), animationIDs.end(), self->preview->animationOverlayID) - animationIDs.begin(); - - if (_imgui_combo(animationOverlayItem, self, &animationIndex)) - self->preview->animationOverlayID = animationIDs[animationIndex]; - - _imgui_drag_float(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, self, self->settings->previewOverlayTransparency); - _imgui_end_child(); //IMGUI_CANVAS_VISUAL_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_HELPER_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_AXES, self, self->settings->previewIsAxes); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_AXES_COLOR, self, self->settings->previewAxesColor); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ALT_ICONS, self, self->settings->previewIsAltIcons); - _imgui_checkbox(IMGUI_CANVAS_ROOT_TRANSFORM, self, self->settings->previewIsRootTransform); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_TRIGGERS, self, self->settings->previewIsTriggers); - _imgui_checkbox(IMGUI_CANVAS_PIVOTS, self, self->settings->previewIsPivots); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_ICONS, self, self->settings->previewIsIcons); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->previewIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_HELPER_CHILD - - ImVec2 previewCursorScreenPos = ImGui::GetCursorScreenPos(); - - if (!self->preview->isRender) size = ivec2(vec2(ImGui::GetContentRegionAvail())); - - preview_draw(self->preview); - ImGui::Image(self->preview->canvas.framebuffer, vec2(size)); - - if (self->settings->previewIsTriggers) - { - Anm2Frame trigger; - anm2_frame_from_time(self->anm2, &trigger, {self->reference->animationID, ANM2_TRIGGERS}, self->preview->time); - - if (trigger.eventID != ID_NONE) - { - f32 textScale = ImGui::GetCurrentWindow()->FontWindowScale; - ImVec2 textPos = previewCursorScreenPos + ImGui::GetStyle().ItemSpacing; - ImGui::SetWindowFontScale(IMGUI_TRIGGERS_FONT_SCALE); - ImGui::GetWindowDrawList()->AddText(textPos, IMGUI_TRIGGERS_EVENT_COLOR, self->anm2->events[trigger.eventID].name.c_str()); - ImGui::SetWindowFontScale(textScale); - } - } - - if (ImGui::IsItemHovered()) - { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } - else - { - _imgui_end(); // IMGUI_ANIMATION_EDITOR - imgui_keyboard_nav_enable(); - return; - } - - _imgui_end(); // IMGUI_ANIMATION_PREVIEW - - mousePos = vec2(ImGui::GetMousePos() - previewCursorScreenPos - pan - (vec2(size) * 0.5f)) / PERCENT_TO_UNIT(zoom); - - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isMod = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - const f32 mouseWheel = ImGui::GetIO().MouseWheel; - - Anm2Frame* frame = nullptr; - - if (self->reference->itemType != ANM2_TRIGGERS) - frame = anm2_frame_from_reference(self->anm2, self->reference); - - f32 step = isMod ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); - - switch (tool) - { - case TOOL_MOVE: - if (!frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isMouseDown) - frame->position = vec2(mousePos); - else - { - if (isLeft) frame->position.x -= step; - if (isRight) frame->position.x += step; - if (isUp) frame->position.y -= step; - if (isDown) frame->position.y += step; - } - break; - case TOOL_ROTATE: - if (!frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_ROTATE); - - if (isMouseDown) - frame->rotation += mouseDelta.x; - else - { - if (isLeft || isUp) frame->rotation -= step; - if (isRight || isDown) frame->rotation += step; - } - break; - case TOOL_SCALE: - if (!frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_SCALE); - - if (isMouseDown) - frame->scale += vec2(mouseDelta.x, mouseDelta.y); - else - { - if (isLeft) frame->scale.x -= step; - if (isRight) frame->scale.x += step; - if (isUp) frame->scale.y -= step; - if (isDown) frame->scale.y += step; - } - break; - default: - break; - } - - if (mouseWheel != 0 || isZoomIn || isZoomOut) - { - f32 delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } -} - -static void _imgui_spritesheet_editor(Imgui* self) -{ - static vec2 mousePos = {0, 0}; - static s32& tool = self->settings->tool; - static vec4& toolColor = self->settings->toolColor; - static ivec2& gridSize = self->settings->editorGridSize; - static ivec2& gridOffset = self->settings->editorGridOffset; - static vec2& pan = self->settings->editorPan; - static f32& zoom = self->settings->editorZoom; - static ivec2& size = self->editor->canvas.size; - - std::string mousePositionString = std::format(IMGUI_POSITION_FORMAT, (s32)mousePos.x, (s32)mousePos.y); - - IMGUI_BEGIN_OR_RETURN(IMGUI_SPRITESHEET_EDITOR, self); - - _imgui_begin_child(IMGUI_CANVAS_GRID_CHILD, self); - _imgui_checkbox(IMGUI_CANVAS_GRID, self, self->settings->editorIsGrid); - ImGui::SameLine(); - _imgui_checkbox(IMGUI_CANVAS_GRID_SNAP, self, self->settings->editorIsGridSnap); - ImGui::SameLine(); - _imgui_color_edit4(IMGUI_CANVAS_GRID_COLOR, self, self->settings->editorGridColor); - _imgui_input_int2(IMGUI_CANVAS_GRID_SIZE, self, gridSize); - _imgui_input_int2(IMGUI_CANVAS_GRID_OFFSET, self, gridOffset); - _imgui_end_child(); - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VIEW_CHILD, self); - _imgui_drag_float(IMGUI_CANVAS_ZOOM, self, zoom); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW.copy({pan == vec2()}), self)) pan = vec2(); - if (_imgui_button(IMGUI_SPRITESHEET_EDITOR_FIT.copy({self->editor->spritesheetID == ID_NONE}), self)) - { - vec4 rect = {0, 0, self->anm2->spritesheets[self->editor->spritesheetID].texture.size.x, - self->anm2->spritesheets[self->editor->spritesheetID].texture.size.y}; - - if ((rect.z > 0 && rect.w > 0)) - { - f32 scaleX = self->editor->canvas.size.x / rect.z; - f32 scaleY = self->editor->canvas.size.y / rect.w; - f32 fitScale = std::min(scaleX, scaleY); - - zoom = UNIT_TO_PERCENT(fitScale); - pan = {}; - } - } - ImGui::Text(mousePositionString.c_str()); - _imgui_end_child(); // IMGUI_CANVAS_VIEW_CHILD - - ImGui::SameLine(); - - _imgui_begin_child(IMGUI_CANVAS_VISUAL_CHILD, self); - _imgui_color_edit4(IMGUI_CANVAS_BACKGROUND_COLOR, self, self->settings->editorBackgroundColor); - _imgui_checkbox(IMGUI_CANVAS_BORDER, self, self->settings->editorIsBorder); - _imgui_end_child(); // IMGUI_CANVAS_VISUAL_CHILD - - ImVec2 editorCursorScreenPos = ImGui::GetCursorScreenPos(); - size = ivec2(vec2(ImGui::GetContentRegionAvail())); - editor_draw(self->editor); - ImGui::Image(self->editor->canvas.framebuffer, vec2(size)); - - if (ImGui::IsItemHovered()) - { - self->pendingCursor = TOOL_CURSORS[tool]; - imgui_keyboard_nav_disable(); - } - else - { - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - imgui_keyboard_nav_enable(); - return; - } - - _imgui_end(); // IMGUI_SPRITESHEET_EDITOR - - mousePos = vec2(ImGui::GetMousePos() - editorCursorScreenPos - pan) / PERCENT_TO_UNIT(zoom); - - const bool isLeft = ImGui::IsKeyPressed(IMGUI_INPUT_LEFT); - const bool isRight = ImGui::IsKeyPressed(IMGUI_INPUT_RIGHT); - const bool isUp = ImGui::IsKeyPressed(IMGUI_INPUT_UP); - const bool isDown = ImGui::IsKeyPressed(IMGUI_INPUT_DOWN); - const bool isShift = ImGui::IsKeyDown(IMGUI_INPUT_SHIFT); - const bool isCtrl = ImGui::IsKeyDown(IMGUI_INPUT_CTRL); - const bool isMouseClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left); - const bool isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); - const bool isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); - const bool isZoomIn = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_IN]); - const bool isZoomOut = _imgui_chord_pressed(imgui_hotkey_chord_registry()[HOTKEY_ZOOM_OUT]); - const f32 mouseWheel = ImGui::GetIO().MouseWheel; - const ImVec2 mouseDelta = ImGui::GetIO().MouseDelta; - - Anm2Frame* frame = nullptr; - if (self->reference->itemType == ANM2_LAYER) - frame = anm2_frame_from_reference(self->anm2, self->reference); - - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->editor->spritesheetID); - Texture* texture = spritesheet ? &spritesheet->texture : nullptr; - - vec2 position = mousePos; - f32 step = isShift ? TOOL_STEP_MOD : TOOL_STEP; - - if ((tool == TOOL_PAN && isMouseDown) || isMouseMiddleDown) - pan += vec2(mouseDelta.x, mouseDelta.y); - - switch (tool) - { - case TOOL_MOVE: - if (!texture || !frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (isMouseDown) - { - if (self->settings->editorIsGridSnap) - { - position.x = roundf((position.x - gridSize.x) / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f); - position.y = roundf((position.y - gridSize.y) / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f); - } - - frame->pivot = position - frame->crop; - } - else - { - if (isLeft) frame->pivot.x -= step; - if (isRight) frame->pivot.x += step; - if (isUp) frame->pivot.y -= step; - if (isDown) frame->pivot.y += step; - } - break; - case TOOL_CROP: - if (!texture || !frame) break; - - if (isMouseClick || isLeft || isRight || isUp || isDown) - imgui_snapshot(self, IMGUI_ACTION_MOVE); - - if (self->settings->editorIsGridSnap) - { - position.x = roundf(position.x / gridSize.x) * gridSize.x + gridOffset.x - (gridSize.x * 0.5f); - position.y = roundf(position.y / gridSize.y) * gridSize.y + gridOffset.y - (gridSize.y * 0.5f); - } - - if (isMouseClick) - { - frame->crop = position; - frame->size = ivec2(0,0); - } - else if (isMouseDown) - frame->size = position - frame->crop; - else - { - if (isCtrl) - { - if (isLeft) frame->crop.x -= step; - if (isRight) frame->crop.x += step; - if (isUp) frame->crop.y -= step; - if (isDown) frame->crop.y += step; - } - else - { - if (isLeft) frame->size.x -= step; - if (isRight) frame->size.x += step; - if (isUp) frame->size.y -= step; - if (isDown) frame->size.y += step; - } - - frame->size.x = std::max({}, frame->size.x); - frame->size.y = std::max({}, frame->size.y); - } - break; - case TOOL_DRAW: - case TOOL_ERASE: - { - if (!texture) break; - - vec4 color = tool == TOOL_ERASE ? COLOR_TRANSPARENT : toolColor; - - if (isMouseClick) - imgui_snapshot(self, tool == TOOL_DRAW ? IMGUI_ACTION_DRAW : IMGUI_ACTION_ERASE); - - if (isMouseDown) - texture_pixel_set(texture, position, color); - break; - } - case TOOL_COLOR_PICKER: - if (isMouseDown) - { - SDL_GetMouseState(&mousePos.x, &mousePos.y); - _imgui_window_color_from_position_get(self->window, mousePos, toolColor); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); - ImGui::BeginTooltip(); - _imgui_color_button(IMGUI_COLOR_PICKER_BUTTON, self, toolColor); - ImGui::EndTooltip(); - ImGui::PopStyleVar(); - } - break; - default: - break; - } - - if (mouseWheel != 0 || isZoomIn || isZoomOut) - { - f32 delta = (mouseWheel > 0 || isZoomIn) ? CANVAS_ZOOM_STEP : -CANVAS_ZOOM_STEP; - zoom = std::clamp(ROUND_NEAREST_MULTIPLE(zoom + delta, CANVAS_ZOOM_STEP), CANVAS_ZOOM_MIN, CANVAS_ZOOM_MAX); - } -} - -static void _imgui_frame_properties(Imgui* self) -{ - static Anm2Type& type = self->reference->itemType; - - IMGUI_BEGIN_OR_RETURN(IMGUI_FRAME_PROPERTIES, self); - - Anm2Frame* frame = anm2_frame_from_reference(self->anm2, self->reference); - - bool isLayerFrame = frame && type == ANM2_LAYER; - - if (!frame || type != ANM2_TRIGGERS) - { - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_CROP.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->crop); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SIZE.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->size); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_POSITION.copy({!frame}), self, !frame ? dummy_value() : frame->position); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_PIVOT.copy({!isLayerFrame}), self, !isLayerFrame ? dummy_value() : frame->pivot); - _imgui_drag_float2(IMGUI_FRAME_PROPERTIES_SCALE.copy({!frame}), self, !frame ? dummy_value() : frame->scale); - _imgui_drag_float(IMGUI_FRAME_PROPERTIES_ROTATION.copy({!frame}), self, !frame ? dummy_value() : frame->rotation); - _imgui_input_int(IMGUI_FRAME_PROPERTIES_DELAY.copy({!frame}), self, !frame ? dummy_value() : frame->delay); - _imgui_color_edit4(IMGUI_FRAME_PROPERTIES_TINT.copy({!frame}), self, !frame ? dummy_value() : frame->tintRGBA); - _imgui_color_edit3(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET.copy({!frame}), self, !frame ? dummy_value() : frame->offsetRGB); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_VISIBLE.copy({!frame}), self, !frame ? dummy_value() : frame->isVisible); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_INTERPOLATED.copy({!frame}), self, !frame ? dummy_value() : frame->isInterpolated); - _imgui_checkbox(IMGUI_FRAME_PROPERTIES_ROUND.copy({!frame}), self, self->settings->propertiesIsRound); - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_X.copy({!frame}), self)) frame->scale.x = -frame->scale.x; - if (_imgui_button(IMGUI_FRAME_PROPERTIES_FLIP_Y.copy({!frame}), self)) frame->scale.y = -frame->scale.y; - - if (self->settings->propertiesIsRound && frame) - { - frame->position = glm::trunc(frame->position); - frame->pivot = glm::trunc(frame->pivot); - frame->crop = glm::trunc(frame->crop); - frame->scale = glm::trunc(frame->scale); - frame->rotation = glm::trunc(frame->rotation); - frame->tintRGBA = glm::trunc(frame->tintRGBA); - frame->offsetRGB = glm::trunc(frame->offsetRGB); - } - } - else - { - std::vector eventIDs; - ImguiItem eventItem = IMGUI_FRAME_PROPERTIES_EVENT.copy({!frame}); - - eventIDs.emplace_back(ID_NONE); - eventItem.items.emplace_back(IMGUI_NONE); - - for (auto & [id, event] : self->anm2->events) - { - eventIDs.emplace_back(id); - eventItem.items.emplace_back(event.name); - } - - s32 eventIndex = std::find(eventIDs.begin(), eventIDs.end(), frame->eventID) - eventIDs.begin(); - - if (_imgui_combo(eventItem, self, &eventIndex)) - frame->eventID = eventIDs[eventIndex]; - - _imgui_input_int(IMGUI_FRAME_PROPERTIES_AT_FRAME.copy({!frame}), self, frame->atFrame); - } - - _imgui_end(); // IMGUI_FRAME_PROPERTIES -} - -static void _imgui_log(Imgui* self) -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle& style = ImGui::GetStyle(); - ImVec4 borderColor = style.Colors[ImGuiCol_Border]; - ImVec4 textColor = style.Colors[ImGuiCol_Text]; - - ImVec2 position = {io.DisplaySize.x - IMGUI_LOG_PADDING, io.DisplaySize.y - IMGUI_LOG_PADDING}; - - for (s32 i = (s32)self->log.size() - 1; i >= 0; --i) - { - ImguiLogItem& item = self->log[i]; - f32 lifetime = item.timeRemaining / IMGUI_LOG_DURATION; - borderColor.w = lifetime; - textColor.w = lifetime; - - item.timeRemaining -= io.DeltaTime; - - if (item.timeRemaining <= 0.0f) - { - self->log.erase(self->log.begin() + i); - continue; - } - - ImGui::SetNextWindowPos(position, ImGuiCond_Always, {1.0f, 1.0f}); - ImGui::PushStyleColor(ImGuiCol_Border, borderColor); - ImGui::PushStyleColor(ImGuiCol_Text, textColor); - ImGui::SetNextWindowBgAlpha(lifetime); - - _imgui_begin(IMGUI_LOG_WINDOW.copy({.label = std::format(IMGUI_LOG_FORMAT, i)}), self); - ImGui::TextUnformatted(item.text.c_str()); - ImVec2 windowSize = ImGui::GetWindowSize(); - _imgui_end(); // IMGUI_LOG_WINDOW - - ImGui::PopStyleColor(2); - - position.y -= windowSize.y + IMGUI_LOG_PADDING; - } -} - -static void _imgui_dock(Imgui* self) -{ - ImguiItem window = IMGUI_WINDOW_MAIN; - ImGuiViewport* viewport = ImGui::GetMainViewport(); - - ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + IMGUI_TASKBAR.size.y)); - ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - IMGUI_TASKBAR.size.y)); - ImGui::SetNextWindowViewport(viewport->ID); - - _imgui_begin(window, self); - _imgui_dockspace(IMGUI_DOCKSPACE_MAIN, self); - - _imgui_tools(self); - _imgui_animations(self); - _imgui_events(self); - _imgui_spritesheets(self); - _imgui_animation_preview(self); - _imgui_spritesheet_editor(self); - _imgui_layers(self); - _imgui_nulls(self); - _imgui_timeline(self); - _imgui_onionskin(self); - _imgui_frame_properties(self); - - _imgui_end(); // IMGUI_WINDOW_MAIN -} - -void imgui_init -( - Imgui* self, - Dialog* dialog, - Resources* resources, - Anm2* anm2, - Anm2Reference* reference, - Editor* editor, - Preview* preview, - GeneratePreview* generatePreview, - Settings* settings, - Snapshots* snapshots, - Clipboard* clipboard, - SDL_Window* window, - SDL_GLContext* glContext -) -{ - IMGUI_CHECKVERSION(); - - self->dialog = dialog; - self->resources = resources; - self->anm2 = anm2; - self->reference = reference; - self->editor = editor; - self->preview = preview; - self->generatePreview = generatePreview; - self->settings = settings; - self->snapshots = snapshots; - self->clipboard = clipboard; - self->window = window; - self->glContext = glContext; - - self->saveAnm2 = *anm2; - - ImGui::CreateContext(); - ImGui::StyleColorsDark(); - - ImGui_ImplSDL3_InitForOpenGL(self->window, *self->glContext); - ImGui_ImplOpenGL3_Init(IMGUI_OPENGL_VERSION); - - ImGuiIO& io = ImGui::GetIO(); - io.IniFilename = nullptr; - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; - io.ConfigWindowsMoveFromTitleBarOnly = true; - - imgui_keyboard_nav_enable(); - - ImGui::LoadIniSettingsFromDisk(settings_path_get().c_str()); - - for (s32 i = 0; i < HOTKEY_COUNT; i++) - { - if (!SETTINGS_HOTKEY_MEMBERS[i]) continue; - imgui_hotkey_chord_registry()[i] = imgui_chord_from_string_get(*&(self->settings->*SETTINGS_HOTKEY_MEMBERS[i])); - } - -} - -void imgui_update(Imgui* self) -{ - ImGui_ImplSDL3_NewFrame(); - ImGui_ImplOpenGL3_NewFrame(); - ImGui::NewFrame(); - - _imgui_taskbar(self); - _imgui_dock(self); - _imgui_log(self); - - if (self->isContextualActionsEnabled) - { - for (const auto& item : imgui_item_registry()) - { - if (item->is_chord() && _imgui_chord_pressed(item->chord_get()) && !item->is_focus_window()) - { - if (item->is_undoable()) imgui_snapshot(self, item->snapshotAction); - if (item->is_function()) item->function(self); - } - } - } - - imgui_contextual_actions_enable(self); - - if (self->pendingCursor != self->cursor) - { - SDL_SetCursor(SDL_CreateSystemCursor(self->pendingCursor)); - self->cursor = self->pendingCursor; - } - - self->pendingCursor = CURSOR_DEFAULT; - - SDL_Event event; - - while(SDL_PollEvent(&event)) - { - ImGui_ImplSDL3_ProcessEvent(&event); - - switch (event.type) - { - case SDL_EVENT_DROP_FILE: - { - const char* droppedFile = event.drop.data; - - if (path_is_extension(droppedFile, ANM2_EXTENSION)) _imgui_anm2_open(self, droppedFile); - else if (path_is_extension(droppedFile, ANM2_SPRITESHEET_EXTENSION)) _imgui_spritesheet_add(self, droppedFile); - else imgui_log_push(self, IMGUI_LOG_DRAG_DROP_ERROR); - - break; - } - case SDL_EVENT_QUIT: - if (self->isTryQuit) self->isQuit = true; - else imgui_quit(self); - break; - default: - break; - } - } -} - -void imgui_draw(void) -{ - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); -} - -void imgui_free(void) -{ - if (!ImGui::GetCurrentContext()) return; - - ImGui_ImplSDL3_Shutdown(); - ImGui_ImplOpenGL3_Shutdown(); - ImGui::SaveIniSettingsToDisk(settings_path_get().c_str()); - ImGui::DestroyContext(); -} \ No newline at end of file diff --git a/src/imgui.h b/src/imgui.h deleted file mode 100644 index 1ccc1f5..0000000 --- a/src/imgui.h +++ /dev/null @@ -1,2586 +0,0 @@ -#pragma once - -#include "clipboard.h" -#include "dialog.h" -#include "editor.h" -#include "ffmpeg.h" -#include "preview.h" -#include "generate_preview.h" -#include "resources.h" -#include "settings.h" -#include "snapshots.h" -#include "tool.h" -#include "window.h" - -#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM -#define IMGUI_ENABLE_DOCKING -#define IM_VEC2_CLASS_EXTRA \ - inline bool operator==(const ImVec2& rhs) const { return x == rhs.x && y == rhs.y; } \ - inline bool operator!=(const ImVec2& rhs) const { return !(*this == rhs); } \ - inline ImVec2 operator+(const ImVec2& rhs) const { return ImVec2(x + rhs.x, y + rhs.y); } \ - inline ImVec2 operator-(const ImVec2& rhs) const { return ImVec2(x - rhs.x, y - rhs.y); } \ - inline ImVec2 operator*(const ImVec2& rhs) const { return ImVec2(x * rhs.x, y * rhs.y); } \ - inline ImVec2 operator*(float s) const { return ImVec2(x * s, y * s); } \ - friend inline ImVec2 operator*(float s, const ImVec2& v) { return ImVec2(v.x * s, v.y * s); } \ - inline ImVec2& operator+=(const ImVec2& rhs) { x += rhs.x; y += rhs.y; return *this; } \ - inline ImVec2& operator-=(const ImVec2& rhs) { x -= rhs.x; y -= rhs.y; return *this; } \ - inline ImVec2& operator*=(float s) { x *= s; y *= s; return *this; } \ - inline ImVec2(const vec2& v) : x(v.x), y(v.y) {} \ - inline operator vec2() const { return vec2(x, y); } - -#define IM_VEC4_CLASS_EXTRA \ - inline bool operator==(const ImVec4& rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; } \ - inline bool operator!=(const ImVec4& rhs) const { return !(*this == rhs); } \ - inline ImVec4 operator+(const ImVec4& rhs) const { return ImVec4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); } \ - inline ImVec4 operator-(const ImVec4& rhs) const { return ImVec4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); } \ - inline ImVec4 operator*(const ImVec4& rhs) const { return ImVec4(x * rhs.x, y * rhs.y, z * rhs.z, w * rhs.w); } \ - inline ImVec4 operator*(float s) const { return ImVec4(x * s, y * s, z * s, w * s); } \ - friend inline ImVec4 operator*(float s, const ImVec4& v) { return ImVec4(v.x * s, v.y * s, v.z * s, v.w * s); } \ - inline ImVec4& operator+=(const ImVec4& rhs) { x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; } \ - inline ImVec4& operator-=(const ImVec4& rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; } \ - inline ImVec4& operator*=(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } \ - inline ImVec4(const vec4& v) : x(v.x), y(v.y), z(v.z), w(v.w) {} \ - inline operator vec4() const { return vec4(x, y, z, w); } - -#include -#include -#include -#include - -#define IMGUI_CHORD_NONE (ImGuiMod_None) -#define IMGUI_EVENTS_FOOTER_HEIGHT 40 -#define IMGUI_FRAME_BORDER 2.0f -#define IMGUI_LOG_DURATION 3.0f -#define IMGUI_LOG_PADDING 10.0f -#define IMGUI_PLAYHEAD_LINE_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX) -#define IMGUI_TRIGGERS_EVENT_COLOR IM_COL32(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, 128) -#define IMGUI_PLAYHEAD_LINE_WIDTH 2.0f -#define IMGUI_SPRITESHEETS_FOOTER_HEIGHT 65 -#define IMGUI_TIMELINE_FRAME_MULTIPLE 5 -#define IMGUI_TIMELINE_MERGE -#define IMGUI_TOOL_COLOR_PICKER_DURATION 0.25f -#define IMGUI_CONFIRM_POPUP_ROW_COUNT 2 -#define IMGUI_CHORD_REPEAT_TIME 0.25f - -#define IMGUI_ACTION_FRAME_CROP "Frame Crop" -#define IMGUI_ACTION_FRAME_MOVE "Frame Move" - -#define IMGUI_ACTION_ANIMATION_SWAP "Animation Swap" -#define IMGUI_ACTION_TRIGGER_MOVE "Trigger At Frame" -#define IMGUI_ACTION_ITEM_SWAP "Item Swap" -#define IMGUI_ACTION_FRAME_DELAY "Frame Delay" -#define IMGUI_ACTION_DRAW "Draw" -#define IMGUI_ACTION_ERASE "Erase" -#define IMGUI_ACTION_MOVE "Move" -#define IMGUI_ACTION_SCALE "Scale" -#define IMGUI_ACTION_ROTATE "Rotate" -#define IMGUI_ACTION_CROP "Crop" -#define IMGUI_ACTION_ADD_SPRITESHEET "Add Spritesheet" -#define IMGUI_ACTION_REPLACE_SPRITESHEET "Replace Spritesheet" -#define IMGUI_ACTION_OPEN_FILE "Open File" - -#define IMGUI_SET_ITEM_PROPERTIES_POPUP "Item Properties" -#define IMGUI_POPUP_FLAGS ImGuiWindowFlags_NoMove -#define IMGUI_POPUP_MODAL_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize - -#define IMGUI_LOG_NO_ANM2_PATH "Please save the .anm2 to a path first!" -#define IMGUI_LOG_FILE_OPEN_FORMAT "Opened anm2: {}" -#define IMGUI_LOG_FILE_SAVE_FORMAT "Saved anm2 to: {}" -#define IMGUI_LOG_SPRITESHEET_RELOAD "Reloaded selected spritesheets" -#define IMGUI_LOG_RENDER_ANIMATION_FRAMES_SAVE_FORMAT "Saved rendered frames to: {}" -#define IMGUI_LOG_RENDER_ANIMATION_SAVE_FORMAT "Saved rendered animation to: {}" -#define IMGUI_LOG_RENDER_ANIMATION_NO_ANIMATION_ERROR "No animation selected; rendering cancelled." -#define IMGUI_LOG_RENDER_ANIMATION_NO_FRAMES_ERROR "No frames to render; rendering cancelled." -#define IMGUI_LOG_RENDER_ANIMATION_DIRECTORY_ERROR "Invalid directory! Make sure it exists and you have write permissions." -#define IMGUI_LOG_RENDER_ANIMATION_PATH_ERROR "Invalid path! Make sure it's valid and you have write permissions." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_PATH_ERROR "Invalid FFmpeg path! Make sure you have it installed and the path is correct." -#define IMGUI_LOG_RENDER_ANIMATION_FFMPEG_ERROR "FFmpeg could not render animation! Check paths or your FFmpeg installation." -#define IMGUI_LOG_SPRITESHEET_SAVE_FORMAT "Saved spritesheet #{} to: {}" -#define IMGUI_LOG_DRAG_DROP_ERROR "Invalid file for dragging/dropping!" -#define IMGUI_LOG_ANIMATION_PASTE_ERROR "Failed to parse clipboard text as an animation." -#define IMGUI_LOG_FRAME_PASTE_ERROR "Failed to parse clipboard text as a frame." -#define IMGUI_LOG_RELOAD_SPRITESHEET "Reloaded spritesheet(s)." - -#define IMGUI_NONE "None" -#define IMGUI_ANIMATION_DEFAULT_FORMAT "(*) {}" -#define IMGUI_BUFFER_MAX UCHAR_MAX -#define IMGUI_INVISIBLE_LABEL_MARKER "##" -#define IMGUI_ITEM_SELECTABLE_EDITABLE_LABEL "## Editing" -#define IMGUI_LOG_FORMAT "## Log {}" -#define IMGUI_LOG_REDO_FORMAT "Redo: {}" -#define IMGUI_LOG_UNDO_FORMAT "Undo: {}" -#define IMGUI_OPENGL_VERSION "#version 330" -#define IMGUI_POSITION_FORMAT "Position: ({:8}, {:8})" -#define IMGUI_SPRITESHEET_FORMAT "#{} {}" -#define IMGUI_SPRITESHEET_ID_FORMAT "#{}" -#define IMGUI_TIMELINE_ITEM_CHILD_FORMAT "#{} {}" -#define IMGUI_LAYER_FORMAT "#{} {}" -#define IMGUI_NULL_FORMAT "#{} {}" -#define IMGUI_TIMELINE_FRAME_LABEL_FORMAT "## {}" -#define IMGUI_SELECTABLE_INPUT_INT_FORMAT "#{}" -#define IMGUI_TIMELINE_ANIMATION_NONE "Select an animation to show timeline..." -#define IMGUI_HOTKEY_CHANGE "Input new hotkey..." -#define IMGUI_LABEL_HOTKEY_FORMAT " ({})" -#define IMGUI_TOOLTIP_HOTKEY_FORMAT "\n(Hotkey: {})" -#define IMGUI_INVISIBLE_FORMAT "## {}" -#define IMGUI_RENDERING_FFMPEG_INFO_THRESHOLD 0.95f - -#define IMGUI_TRIGGERS_FONT_SCALE 2.0 - -const ImVec2 IMGUI_TIMELINE_FRAME_SIZE = {12, 36}; -const ImVec2 IMGUI_TIMELINE_FRAME_ATLAS_OFFSET = {ATLAS_SIZE_SMALL.x * 0.25f, (IMGUI_TIMELINE_FRAME_SIZE.y * 0.5f) - (ATLAS_SIZE_SMALL.y * 0.5f)}; -const ImVec2 IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE = {150, 0}; -const ImVec2 IMGUI_TIMELINE_ITEM_SIZE = {300, IMGUI_TIMELINE_FRAME_SIZE.y}; - -const ImVec4 IMGUI_TIMELINE_FRAME_COLOR = {0.0f, 0.0f, 0.0f, 0.125}; -const ImVec4 IMGUI_TIMELINE_FRAME_MULTIPLE_COLOR = {0.113, 0.184, 0.286, 0.125}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_COLOR = {0.113, 0.184, 0.286, 0.5}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_COLOR = {0.113, 0.184, 0.286, 1.0}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_INACTIVE_COLOR = {0.113, 0.184, 0.286, 0.125}; -const ImVec4 IMGUI_TIMELINE_HEADER_FRAME_MULTIPLE_INACTIVE_COLOR = {0.113, 0.184, 0.286, 0.25}; -const ImVec4 IMGUI_ACTIVE_COLOR = {1.0, 1.0, 1.0, 1.0}; -const ImVec4 IMGUI_INACTIVE_COLOR = {1.0, 1.0, 1.0, 0.25}; - -const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {50.0, 50.0}; -const ImVec2 IMGUI_TOOLTIP_OFFSET = {16, 8}; -const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1}; - -const ImGuiKey IMGUI_INPUT_DELETE = ImGuiKey_Delete; -const ImGuiKey IMGUI_INPUT_LEFT = ImGuiKey_LeftArrow; -const ImGuiKey IMGUI_INPUT_RIGHT = ImGuiKey_RightArrow; -const ImGuiKey IMGUI_INPUT_UP = ImGuiKey_UpArrow; -const ImGuiKey IMGUI_INPUT_DOWN = ImGuiKey_DownArrow; -const ImGuiKey IMGUI_INPUT_SHIFT = ImGuiMod_Shift; -const ImGuiKey IMGUI_INPUT_CTRL = ImGuiMod_Ctrl; -const ImGuiKey IMGUI_INPUT_ZOOM_IN = ImGuiKey_1; -const ImGuiKey IMGUI_INPUT_ZOOM_OUT = ImGuiKey_2; -const ImGuiKey IMGUI_INPUT_ENTER = ImGuiKey_Enter; -const ImGuiKey IMGUI_INPUT_RENAME = ImGuiKey_F2; -const ImGuiKey IMGUI_INPUT_DEFAULT = ImGuiKey_Home; -const ImGuiMouseButton IMGUI_MOUSE_DEFAULT = ImGuiMouseButton_Middle; - -enum ImguiPopupType -{ - IMGUI_POPUP_NONE, - IMGUI_POPUP_BY_ITEM, - IMGUI_POPUP_CENTER_WINDOW -}; - -enum ImguiPopupState -{ - IMGUI_POPUP_STATE_CLOSED, - IMGUI_POPUP_STATE_OPEN, - IMGUI_POPUP_STATE_CONFIRM, - IMGUI_POPUP_STATE_CANCEL -}; - -struct ImguiColorSet -{ - ImVec4 normal{}; - ImVec4 active{}; - ImVec4 hovered{}; - ImVec4 border{}; - - bool is_normal() const { return normal != ImVec4(); } - bool is_active() const { return active != ImVec4(); } - bool is_hovered() const { return hovered != ImVec4(); } - bool is_border() const { return border != ImVec4(); } -}; - -struct ImguiLogItem -{ - std::string text; - f32 timeRemaining; -}; - -struct Imgui -{ - Dialog* dialog = nullptr; - Resources* resources = nullptr; - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Editor* editor = nullptr; - Preview* preview = nullptr; - GeneratePreview* generatePreview = nullptr; - Settings* settings = nullptr; - Snapshots* snapshots = nullptr; - Clipboard* clipboard = nullptr; - SDL_Window* window = nullptr; - SDL_GLContext* glContext = nullptr; - std::string pendingPopup{}; - ImguiPopupType pendingPopupType = IMGUI_POPUP_NONE; - ImVec2 pendingPopupPosition{}; - std::vector log; - Anm2 saveAnm2; - SDL_SystemCursor cursor; - SDL_SystemCursor pendingCursor; - bool isCursorSet = false; - bool isContextualActionsEnabled = true; - bool isQuit = false; - bool isTryQuit = false; -}; - -static inline void imgui_snapshot(Imgui* self, const std::string& action = SNAPSHOT_ACTION) -{ - self->snapshots->action = action; - Snapshot snapshot = snapshot_get(self->snapshots); - snapshots_undo_push(self->snapshots, &snapshot); -} - -static void imgui_log_push(Imgui* self, const std::string& text) -{ - self->log.push_back({text, IMGUI_LOG_DURATION}); - log_imgui(text); -} - -static inline void imgui_anm2_new(Imgui* self) -{ - anm2_reference_clear(self->reference); - anm2_free(self->anm2); - anm2_new(self->anm2); -} - -static inline void imgui_file_open(Imgui* self) -{ - dialog_anm2_open(self->dialog); -} - -static inline void imgui_file_save(Imgui* self) -{ - if (self->anm2->path.empty()) - dialog_anm2_save(self->dialog); - else - { - anm2_serialize(self->anm2, self->anm2->path); - imgui_log_push(self, std::format(IMGUI_LOG_FILE_SAVE_FORMAT, self->anm2->path)); - } - - self->saveAnm2 = *self->anm2; -} - -static inline void imgui_file_new(Imgui* self) -{ - std::string path = self->anm2->path; - imgui_anm2_new(self); - self->anm2->path = path; - imgui_file_save(self); -} - -static inline void imgui_file_save_as(Imgui* self) -{ - dialog_anm2_save(self->dialog); -} - -static inline void imgui_quit(Imgui* self) -{ - if (self->saveAnm2 != *self->anm2) - self->isTryQuit = true; - else - self->isQuit = true; -} - -static inline void imgui_explore(Imgui* self) -{ - std::filesystem::path filePath = self->anm2->path; - std::filesystem::path parentPath = filePath.parent_path(); - dialog_explorer_open(parentPath.string()); -} - -static inline void imgui_tool_pan_set(Imgui* self) -{ - self->settings->tool = TOOL_PAN; -} - -static inline void imgui_tool_move_set(Imgui* self) -{ - self->settings->tool = TOOL_MOVE; -} - -static inline void imgui_tool_rotate_set(Imgui* self) -{ - self->settings->tool = TOOL_ROTATE; -} - -static inline void imgui_tool_scale_set(Imgui* self) -{ - self->settings->tool = TOOL_SCALE; -} - -static inline void imgui_tool_crop_set(Imgui* self) -{ - self->settings->tool = TOOL_CROP; -} - -static inline void imgui_tool_draw_set(Imgui* self) -{ - self->settings->tool = TOOL_DRAW; -} - -static inline void imgui_tool_erase_set(Imgui* self) -{ - self->settings->tool = TOOL_ERASE; -} - -static inline void imgui_tool_color_picker_set(Imgui* self) -{ - self->settings->tool = TOOL_COLOR_PICKER; -} - -static inline void imgui_undo(Imgui* self) -{ - if (self->snapshots->undoStack.top == 0) return; - - snapshots_undo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_UNDO_FORMAT, self->snapshots->action)); -} - -static inline void imgui_redo(Imgui* self) -{ - if (self->snapshots->redoStack.top == 0) return; - - std::string action = self->snapshots->action; - snapshots_redo(self->snapshots); - imgui_log_push(self, std::format(IMGUI_LOG_REDO_FORMAT, action)); -} - -static inline void imgui_cut(Imgui* self) -{ - clipboard_cut(self->clipboard); -} - -static inline void imgui_copy(Imgui* self) -{ - clipboard_copy(self->clipboard); -} - -static inline void imgui_paste(Imgui* self) -{ - if (!clipboard_paste(self->clipboard)) - { - switch (self->clipboard->type) - { - case CLIPBOARD_FRAME: imgui_log_push(self, IMGUI_LOG_FRAME_PASTE_ERROR); break; - case CLIPBOARD_ANIMATION: imgui_log_push(self, IMGUI_LOG_ANIMATION_PASTE_ERROR); break; - default: break; - } - } -} - -static inline void imgui_onionskin_toggle(Imgui* self) -{ - self->settings->onionskinIsEnabled = !self->settings->onionskinIsEnabled; -} - -static const std::unordered_map IMGUI_KEY_MAP = -{ - { "A", ImGuiKey_A }, - { "B", ImGuiKey_B }, - { "C", ImGuiKey_C }, - { "D", ImGuiKey_D }, - { "E", ImGuiKey_E }, - { "F", ImGuiKey_F }, - { "G", ImGuiKey_G }, - { "H", ImGuiKey_H }, - { "I", ImGuiKey_I }, - { "J", ImGuiKey_J }, - { "K", ImGuiKey_K }, - { "L", ImGuiKey_L }, - { "M", ImGuiKey_M }, - { "N", ImGuiKey_N }, - { "O", ImGuiKey_O }, - { "P", ImGuiKey_P }, - { "Q", ImGuiKey_Q }, - { "R", ImGuiKey_R }, - { "S", ImGuiKey_S }, - { "T", ImGuiKey_T }, - { "U", ImGuiKey_U }, - { "V", ImGuiKey_V }, - { "W", ImGuiKey_W }, - { "X", ImGuiKey_X }, - { "Y", ImGuiKey_Y }, - { "Z", ImGuiKey_Z }, - - { "0", ImGuiKey_0 }, - { "1", ImGuiKey_1 }, - { "2", ImGuiKey_2 }, - { "3", ImGuiKey_3 }, - { "4", ImGuiKey_4 }, - { "5", ImGuiKey_5 }, - { "6", ImGuiKey_6 }, - { "7", ImGuiKey_7 }, - { "8", ImGuiKey_8 }, - { "9", ImGuiKey_9 }, - - { "Num0", ImGuiKey_Keypad0 }, - { "Num1", ImGuiKey_Keypad1 }, - { "Num2", ImGuiKey_Keypad2 }, - { "Num3", ImGuiKey_Keypad3 }, - { "Num4", ImGuiKey_Keypad4 }, - { "Num5", ImGuiKey_Keypad5 }, - { "Num6", ImGuiKey_Keypad6 }, - { "Num7", ImGuiKey_Keypad7 }, - { "Num8", ImGuiKey_Keypad8 }, - { "Num9", ImGuiKey_Keypad9 }, - { "NumAdd", ImGuiKey_KeypadAdd }, - { "NumSubtract", ImGuiKey_KeypadSubtract }, - { "NumMultiply", ImGuiKey_KeypadMultiply }, - { "NumDivide", ImGuiKey_KeypadDivide }, - { "NumEnter", ImGuiKey_KeypadEnter }, - { "NumDecimal", ImGuiKey_KeypadDecimal }, - - { "F1", ImGuiKey_F1 }, - { "F2", ImGuiKey_F2 }, - { "F3", ImGuiKey_F3 }, - { "F4", ImGuiKey_F4 }, - { "F5", ImGuiKey_F5 }, - { "F6", ImGuiKey_F6 }, - { "F7", ImGuiKey_F7 }, - { "F8", ImGuiKey_F8 }, - { "F9", ImGuiKey_F9 }, - { "F10", ImGuiKey_F10 }, - { "F11", ImGuiKey_F11 }, - { "F12", ImGuiKey_F12 }, - - { "Up", ImGuiKey_UpArrow }, - { "Down", ImGuiKey_DownArrow }, - { "Left", ImGuiKey_LeftArrow }, - { "Right", ImGuiKey_RightArrow }, - - { "Space", ImGuiKey_Space }, - { "Enter", ImGuiKey_Enter }, - { "Escape", ImGuiKey_Escape }, - { "Tab", ImGuiKey_Tab }, - { "Backspace", ImGuiKey_Backspace }, - { "Delete", ImGuiKey_Delete }, - { "Insert", ImGuiKey_Insert }, - { "Home", ImGuiKey_Home }, - { "End", ImGuiKey_End }, - { "PageUp", ImGuiKey_PageUp }, - { "PageDown", ImGuiKey_PageDown }, - - { "Minus", ImGuiKey_Minus }, - { "Equal", ImGuiKey_Equal }, - { "LeftBracket", ImGuiKey_LeftBracket }, - { "RightBracket", ImGuiKey_RightBracket }, - { "Semicolon", ImGuiKey_Semicolon }, - { "Apostrophe", ImGuiKey_Apostrophe }, - { "Comma", ImGuiKey_Comma }, - { "Period", ImGuiKey_Period }, - { "Slash", ImGuiKey_Slash }, - { "Backslash", ImGuiKey_Backslash }, - { "GraveAccent", ImGuiKey_GraveAccent }, - - { "MouseLeft", ImGuiKey_MouseLeft }, - { "MouseRight", ImGuiKey_MouseRight }, - { "MouseMiddle", ImGuiKey_MouseMiddle }, - { "MouseX1", ImGuiKey_MouseX1 }, - { "MouseX2", ImGuiKey_MouseX2 } -}; - -static std::unordered_map IMGUI_MOD_MAP = -{ - { "Ctrl", ImGuiMod_Ctrl }, - { "Shift", ImGuiMod_Shift }, - { "Alt", ImGuiMod_Alt }, - { "Super", ImGuiMod_Super }, -}; - -static inline ImGuiKey imgui_key_from_char_get(char c) -{ - if (c >= 'a' && c <= 'z') c -= 'a' - 'A'; - if (c >= 'A' && c <= 'Z') return (ImGuiKey)(ImGuiKey_A + (c - 'A')); - return ImGuiKey_None; -} - -static inline std::string imgui_string_from_chord_get(ImGuiKeyChord chord) -{ - std::string result; - - if (chord & ImGuiMod_Ctrl) result += "Ctrl+"; - if (chord & ImGuiMod_Shift) result += "Shift+"; - if (chord & ImGuiMod_Alt) result += "Alt+"; - if (chord & ImGuiMod_Super) result += "Super+"; - - ImGuiKey key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); - - if (key != ImGuiKey_None) - { - const char* name = ImGui::GetKeyName(key); - if (name && *name) - result += name; - else - result += "Unknown"; - } - - if (!result.empty() && result.back() == '+') - result.pop_back(); - - return result; -} - -static inline ImGuiKeyChord imgui_chord_from_string_get(const std::string& str) -{ - ImGuiKeyChord chord = 0; - ImGuiKey baseKey = ImGuiKey_None; - - std::stringstream ss(str); - std::string token; - while (std::getline(ss, token, '+')) - { - // trim - token.erase(0, token.find_first_not_of(" \t\r\n")); - token.erase(token.find_last_not_of(" \t\r\n") + 1); - - if (token.empty()) - continue; - - if (auto it = IMGUI_MOD_MAP.find(token); it != IMGUI_MOD_MAP.end()) { - chord |= it->second; - } - else if (baseKey == ImGuiKey_None) { - if (auto it2 = IMGUI_KEY_MAP.find(token); it2 != IMGUI_KEY_MAP.end()) - baseKey = it2->second; - } - } - - if (baseKey != ImGuiKey_None) - chord |= baseKey; - - return chord; -} - -static inline void imgui_keyboard_nav_enable(void) { ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; } -static inline void imgui_keyboard_nav_disable(void) { ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NavEnableKeyboard; } -static inline void imgui_contextual_actions_enable(Imgui* self) { self->isContextualActionsEnabled = true; } -static inline void imgui_contextual_actions_disable(Imgui* self){ self->isContextualActionsEnabled = false; } -static inline bool imgui_is_popup_open(const std::string& label) { return ImGui::IsPopupOpen(label.c_str()); } - -static inline bool imgui_is_any_popup_open(void) -{ - return ImGui::IsPopupOpen(nullptr, ImGuiPopupFlags_AnyPopupId); -} - -static inline void imgui_open_popup(const std::string& label) { ImGui::OpenPopup(label.c_str()); } -static inline void imgui_pending_popup_process(Imgui* self) -{ - if (self->pendingPopup.empty()) return; - - switch (self->pendingPopupType) - { - case IMGUI_POPUP_CENTER_WINDOW: - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - break; - case IMGUI_POPUP_BY_ITEM: - default: - ImGui::SetNextWindowPos(self->pendingPopupPosition); - break; - } - - imgui_open_popup(self->pendingPopup.c_str()); - - self->pendingPopup.clear(); - self->pendingPopupType = IMGUI_POPUP_NONE; - self->pendingPopupPosition = ImVec2(); -} - -static inline bool imgui_begin_popup(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) -{ - imgui_pending_popup_process(imgui); - if (size != ImVec2()) ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopup(label.c_str(), IMGUI_POPUP_FLAGS); - return isActivated; -} - -static inline bool imgui_begin_popup_modal(const std::string& label, Imgui* imgui, ImVec2 size = ImVec2()) -{ - imgui_pending_popup_process(imgui); - if (size != ImVec2()) ImGui::SetNextWindowSizeConstraints(size, ImVec2(FLT_MAX, FLT_MAX)); - bool isActivated = ImGui::BeginPopupModal(label.c_str(), nullptr, IMGUI_POPUP_MODAL_FLAGS); - if (isActivated) imgui_contextual_actions_disable(imgui); - return isActivated; -} - -static inline void imgui_close_current_popup(Imgui* imgui) -{ - imgui_contextual_actions_enable(imgui); - ImGui::CloseCurrentPopup(); -} - -static inline void imgui_end_popup(Imgui* imgui) -{ - ImGui::EndPopup(); - imgui_pending_popup_process(imgui); -} - -enum ImguiItemType -{ - IMGUI_ITEM, - IMGUI_TEXT, - IMGUI_WINDOW, - IMGUI_DOCKSPACE, - IMGUI_CHILD, - IMGUI_TABLE, - IMGUI_CONFIRM_POPUP, - IMGUI_SELECTABLE, - IMGUI_BUTTON, - IMGUI_RADIO_BUTTON, - IMGUI_COLOR_BUTTON, - IMGUI_CHECKBOX, - IMGUI_INPUT_INT, - IMGUI_INPUT_TEXT, - IMGUI_INPUT_FLOAT, - IMGUI_SLIDER_FLOAT, - IMGUI_DRAG_FLOAT, - IMGUI_COLOR_EDIT, - IMGUI_COMBO, - IMGUI_ATLAS_BUTTON -}; - -struct ImguiItemOverride -{ - bool isDisabled{}; - bool isSelected{}; - std::string label{}; - ImVec2 size{}; - s32 id{}; - s32 max{}; - AtlasType atlas = ATLAS_NONE; - bool isMnemonicDisabled{}; - s32 value{}; - s32 rowCount{}; -}; - -struct ImguiItem; - -static std::vector& imgui_item_registry(void) -{ - static std::vector registry; - return registry; -} - -static ImGuiKeyChord* imgui_hotkey_chord_registry(void) -{ - static ImGuiKeyChord registry[HOTKEY_COUNT]; - return registry; -} - -typedef void(*ImguiFunction)(Imgui*); - -// Item -struct ImguiItem -{ - std::string label{}; - std::string tooltip{}; - std::string& text = tooltip; - std::string snapshotAction{}; - std::string popup{}; - std::string dragDrop{}; - std::string focusWindow{}; - std::vector items{}; - AtlasType atlas = ATLAS_NONE; - ImGuiKeyChord chord = IMGUI_CHORD_NONE; - HotkeyType hotkey = HOTKEY_NONE; - ImGuiKey mnemonicKey = ImGuiKey_None; - s32 mnemonicIndex = INDEX_NONE; - ImVec2 size{}; - ImVec2 popupSize{}; - ImguiColorSet color{}; - ImguiFunction function = nullptr; - ImguiPopupType popupType = IMGUI_POPUP_CENTER_WINDOW; - bool isDisabled = false; - bool isMnemonicDisabled = false; - bool isEmptyFormat = false; - bool isSelected = false; - bool isUseItemActivated = false; - bool isSizeToText = false; - bool isHotkeyInLabel = false; - bool isSameLine = false; - bool isSeparator = false; - s32 id = 0; - s32 idOffset{}; - f32 speed = 0.25f; - s32 step = 1; - s32 stepFast = 10; - s32 min{}; - s32 max{}; - s32 value{}; - vec2 atlasOffset{}; - s32 border{}; - s32 flags{}; - s32 windowFlags{}; - s32 rowCount = 0; - - bool is_border() const { return border != 0; } - bool is_row() const { return rowCount != 0; } - bool is_hotkey() const { return hotkey != HOTKEY_NONE; } - bool is_chord() const { return chord != IMGUI_CHORD_NONE || is_hotkey(); } - bool is_drag_drop() const { return !dragDrop.empty(); } - bool is_focus_window() const { return !focusWindow.empty(); } - bool is_popup() const { return !popup.empty(); } - bool is_function() const { return function; } - bool is_size() const { return size != ImVec2(); } - bool is_popup_size() const { return popupSize != ImVec2(); } - bool is_tooltip() const { return !tooltip.empty(); } - bool is_undoable() const { return !snapshotAction.empty(); } - bool is_mnemonic() const { return mnemonicKey != ImGuiKey_None; } - bool is_range() const { return min != 0 || max != 0; } - const char* drag_drop_get() const { return dragDrop.c_str(); } - const char* text_get() const { return text.c_str(); } - - void construct() - { - static s32 idNew = 0; - id = idNew++; - - imgui_item_registry().push_back(this); - - std::string labelNew{}; - - for (s32 i = 0; i < (s32)label.size(); i++) - { - if (label[i] == '&') - { - if (label[i + 1] == '&') - { - labelNew += '&'; - i++; - } - else if (label[i + 1] != '\0') - { - mnemonicKey = imgui_key_from_char_get(label[i + 1]); - mnemonicIndex = (s32)labelNew.size(); - labelNew += label[i + 1]; - i++; - } - } - else - labelNew += label[i]; - } - - label = labelNew; - } - - ImguiItem copy(const ImguiItemOverride& override) const - { - ImguiItem out = *this; - if (override.isDisabled) out.isDisabled = override.isDisabled; - if(override.isSelected) out.isSelected = override.isSelected; - if (is_popup() && imgui_is_popup_open(popup)) out.isSelected = true; - if (id != ID_NONE) out.id = id + idOffset + override.id; - if (!override.label.empty()) out.label = override.label; - if (override.size != ImVec2{}) out.size = override.size; - if (override.max != 0) out.max = override.max; - if (override.value != 0) out.value = override.value; - if (override.rowCount != 0) out.rowCount = override.rowCount; - if (override.atlas != ATLAS_NONE) out.atlas = override.atlas; - if (override.isMnemonicDisabled) out.isMnemonicDisabled = override.isMnemonicDisabled; - return out; - } - - ImGuiKeyChord chord_get() const - { - if (is_hotkey()) return imgui_hotkey_chord_registry()[hotkey]; - return chord; - } - - std::string label_get() const - { - std::string newLabel = label; - if (isHotkeyInLabel) - newLabel += std::format(IMGUI_LABEL_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newLabel; - } - - std::string tooltip_get() const - { - std::string newTooltip = tooltip; - if (is_chord()) - newTooltip += std::format(IMGUI_TOOLTIP_HOTKEY_FORMAT, imgui_string_from_chord_get(chord_get())); - return newTooltip; - } -}; - -#define IMGUI_ITEM(NAME, ...) const inline ImguiItem NAME = []{ ImguiItem self; __VA_ARGS__; self.construct(); return self; }() - -IMGUI_ITEM(IMGUI_WINDOW_MAIN, - self.label = "## Window", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBringToFrontOnFocus | - ImGuiWindowFlags_NoNavFocus -); - -IMGUI_ITEM(IMGUI_DOCKSPACE_MAIN, - self.label = "## Dockspace", - self.flags = ImGuiDockNodeFlags_PassthruCentralNode -); - -IMGUI_ITEM(IMGUI_FOOTER_CHILD, - self.label = "## Footer Child", - self.size = {0, 36}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_TASKBAR, - self.label = "Taskbar", - self.size = {0, 32}, - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse | - ImGuiWindowFlags_NoSavedSettings -); - -IMGUI_ITEM(IMGUI_FILE, - self.label = "&File", - self.tooltip = "Opens the file menu, for reading/writing anm2 files.", - self.popup = "## File Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_NEW, - self.label = "&New ", - self.tooltip = "Load a blank .anm2 file to edit.", - self.function = imgui_file_new, - self.hotkey = HOTKEY_NEW, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); - -IMGUI_ITEM(IMGUI_OPEN, - self.label = "&Open ", - self.tooltip = "Open an existing .anm2 file to edit.", - self.function = imgui_file_open, - self.hotkey = HOTKEY_OPEN, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); - -IMGUI_ITEM(IMGUI_SAVE, - self.label = "&Save ", - self.tooltip = "Saves the current .anm2 file to its path.\nIf no path exists, one can be chosen.", - self.function = imgui_file_save, - self.hotkey = HOTKEY_SAVE, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); - -IMGUI_ITEM(IMGUI_SAVE_AS, - self.label = "S&ave As ", - self.tooltip = "Saves the current .anm2 file to a chosen path.", - self.function = imgui_file_save_as, - self.hotkey = HOTKEY_SAVE_AS, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); - -IMGUI_ITEM(IMGUI_EXPLORE_ANM2_LOCATION, - self.label = "E&xplore Anm2 Location", - self.tooltip = "Open the system's file explorer in the anm2's path.", - self.function = imgui_explore, - self.isSizeToText = true, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_EXIT, - self.label = "&Exit ", - self.tooltip = "Exits the program.", - self.function = imgui_quit, - self.hotkey = HOTKEY_EXIT, - self.isSizeToText = true, - self.isHotkeyInLabel = true -); - -IMGUI_ITEM(IMGUI_EXIT_CONFIRMATION, - self.label = "Exit Confirmation", - self.text = "Unsaved changes will be lost!\nAre you sure you want to exit?" -); - -IMGUI_ITEM(IMGUI_OPEN_CONFIRMATION, - self.label = "Open Confirmation", - self.text = "Unsaved changes will be lost!\nAre you sure you open a new file?" -); - -IMGUI_ITEM(IMGUI_NO_ANM2_PATH_CONFIRMATION, - self.label = "No Anm2 Path", - self.text = "You will need to load or make a new .anm2 file first!\n" -); - -IMGUI_ITEM(IMGUI_WIZARD, - self.label = "&Wizard", - self.tooltip = "Opens the wizard menu, for neat functions related to the .anm2.", - self.popup = "## Wizard Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); - -#define IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING 40 -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID, - self.label = "&Generate Animation from Grid", - self.tooltip = "Generate a new animation from grid values.", - self.popup = "Generate Animation from Grid", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = - { - (GENERATE_PREVIEW_SIZE.x * 2) + IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING, - GENERATE_PREVIEW_SIZE.y + (IMGUI_FOOTER_CHILD.size.y * 2) + (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING / 2) - } -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_OPTIONS_CHILD, - self.label = "## Generate Animation From Grid Options Child", - self.size = - { - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2, - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_START_POSITION, - self.label = "Start Position", - self.tooltip = "Set the starting position on the layer's spritesheet for the generated animation." -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SIZE, - self.label = "Size", - self.tooltip = "Set the size of each frame in the generated animation." -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PIVOT, - self.label = "Pivot", - self.tooltip = "Set the pivot of each frame in the generated animation." -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_ROWS, - self.label = "Rows", - self.tooltip = "Set how many rows will be used in the generated animation.", - self.min = 1, - self.max = 1000 -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COLUMNS, - self.label = "Columns", - self.tooltip = "Set how many columns will be used in the generated animation.", - self.min = 1, - self.max = 1000 -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_COUNT, - self.label = "Count", - self.tooltip = "Set how many frames will be made for the generated animation.", - self.value = ANM2_FRAME_NUM_MIN -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_DELAY, - self.label = "Delay", - self.tooltip = "Set the delay of each frame in the generated animation.", - self.max = 1000 -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_PREVIEW_CHILD, - self.label = "## Generate Animation From Grid Preview Child", - self.size = - { - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2, - IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.y - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER_CHILD, - self.label = "## Generate Animation From Grid Slider Child", - self.size = - { - (IMGUI_GENERATE_ANIMATION_FROM_GRID.popupSize.x / 2) - (IMGUI_GENERATE_ANIMATION_FROM_GRID_PADDING / 2), - IMGUI_FOOTER_CHILD.size.y - }, - self.flags = true -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_SLIDER, - self.label = "## Generate Animation From Grid Slider", - self.tooltip = "Change the time of the generated animation preview.", - self.min = GENERATE_PREVIEW_TIME_MIN, - self.max = GENERATE_PREVIEW_TIME_MAX, - self.value = GENERATE_PREVIEW_TIME_MIN, - self.rowCount = 1, - self.isEmptyFormat = true, - self.flags = ImGuiSliderFlags_NoInput -); - -IMGUI_ITEM(IMGUI_GENERATE_ANIMATION_FROM_GRID_GENERATE, - self.label = "Generate", - self.tooltip = "Generate an animation with the used settings.", - self.snapshotAction = "Generate Animation from Grid", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES, - self.label = "&Change All Frame Properties", - self.tooltip = "Change all frame properties in the selected animation item (or selected frame).", - self.popup = "Change All Frame Properties", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {500, 405} -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CHILD, - self.label = "## Change All Frame Properties Child", - self.size = - { - IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, - 275 - }, - self.flags = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS_CHILD, - self.label = "## Change All Frame Properties Settings Child", - self.size = - { - IMGUI_CHANGE_ALL_FRAME_PROPERTIES.popupSize.x, - 55 - }, - self.flags = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SETTINGS, self.label = "Settings"); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_FROM_SELECTED_FRAME, - self.label = "From Selected Frames", - self.tooltip = "The set frame properties will start from the selected frame.", - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_NUMBER_FRAMES, - self.label = "# of Frames", - self.tooltip = "Set the amount of frames that the set frame properties will apply to.", - self.size = {200, 0}, - self.value = ANM2_FRAME_NUM_MIN, - self.max = 1000 -); - -#define IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT 4 -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_ADD, - self.label = "Add", - self.tooltip = "The specified values will be added to all specified frames.", - self.snapshotAction = "Add Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SUBTRACT, - self.label = "Subtract", - self.tooltip = "The specified values will be subtracted from all selected frames.", - self.snapshotAction = "Subtract Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_SET, - self.label = "Set", - self.tooltip = "The specified values will be set to the specified value in selected frames.", - self.snapshotAction = "Set Frame Properties", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CHANGE_ALL_FRAME_PROPERTIES_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel changing all frame properties.", - self.rowCount = IMGUI_CHANGE_ALL_FRAME_PROPERTIES_OPTIONS_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_SCALE_ANM2, - self.label = "S&cale Anm2", - self.tooltip = "Scale up all size and position-related frame properties in the anm2.", - self.popup = "Scale Anm2", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {260, 75}, - self.isSizeToText = true, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_OPTIONS_CHILD, - self.label = "## Scale Anm2 Options Child", - self.size = {IMGUI_SCALE_ANM2.popupSize.x, IMGUI_SCALE_ANM2.popupSize.y - IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_VALUE, - self.label = "Value", - self.tooltip = "The size and position-related frame properties in the anm2 will be scaled by this value.", - self.value = 1, - self.step = 0.25, - self.stepFast = 1 -); - -IMGUI_ITEM(IMGUI_SCALE_ANM2_SCALE, - self.label = "Scale", - self.tooltip = "Scale the anm2 with the value specified.", - self.snapshotAction = "Scale Anm2", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION, - self.label = "&Render Animation", - self.tooltip = "Renders the current animation preview; output options can be customized.", - self.popup = "Render Animation", - self.popupSize = {500, 170}, - self.popupType = IMGUI_POPUP_CENTER_WINDOW -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CHILD, - self.label = "## Render Animation Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_RENDER_ANIMATION.popupSize.y - IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FOOTER_CHILD, - self.label = "## Render Animation Footer Child", - self.size = {IMGUI_RENDER_ANIMATION.popupSize.x, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION_BROWSE, - self.label = "## Location Browse", - self.tooltip = "Open file explorer to pick rendered animation location.", - self.atlas = ATLAS_FOLDER, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_LOCATION, - self.label = "Location", - self.tooltip = "Select the location of the rendered animation.\nFor PNG images, this should be a directory, otherwise, a filepath.", - self.max = 1024 -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_BROWSE, - self.label = "## FFMpeg Browse", - self.tooltip = "Open file explorer to pick the path of FFmpeg", - self.atlas = ATLAS_FOLDER, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FFMPEG_PATH, - self.label = "FFmpeg Path", - self.tooltip = "Sets the path FFmpeg currently resides in.\nFFmpeg is required for rendering animations.\nDownload it from https://ffmpeg.org/, your package manager, or wherever else.", - self.max = 1024 -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_OUTPUT, - self.label = "Output", - self.tooltip = "Select the rendered animation output.\nIt can either be one animated image or a sequence of frames.", - self.items = {std::begin(RENDER_TYPE_STRINGS), std::end(RENDER_TYPE_STRINGS)}, - self.value = RENDER_PNG -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_FORMAT, - self.label = "Format", - self.tooltip = "(PNG images only).\nSet the format of each output frame; i.e., its filename.\nThe format will only take one argument; that being the frame's index.\nFor example, a format like \"{}.png\" will export a frame of index 0 as \"0.png\".", - self.max = UCHAR_MAX -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_IS_USE_ANIMATION_BOUNDS, - self.label = "Use Animation Bounds", - self.tooltip = "Instead of using the animation preview's bounds, the rendered animation will use the animation's bounds.\nNOTE: If you're looking to make a transparent animation, set the preview background to be transparent\nand toggle off other drawn things.", - self.value = SETTINGS_RENDER_IS_USE_ANIMATION_BOUNDS_DEFAULT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_SCALE, - self.label = "Scale", - self.tooltip = "Change the scale the animation will be rendered at.", - self.value = SETTINGS_RENDER_SCALE_DEFAULT, - self.size = {125, 0} -); - -IMGUI_ITEM(IMGUI_RENDER_ANIMATION_CONFIRM, - self.label = "Render", - self.tooltip = "Render the animation, with the used settings.", - self.popup = "Rendering Animation...", - self.popupType = IMGUI_POPUP_CENTER_WINDOW, - self.popupSize = {300, 60}, - self.isSameLine = true, - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CHILD, - self.label = "##Rendering Child", - self.size = {400.0f, 65.0f}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_INFO, self.label = "Recording frames. Once done, the program may halt\nas FFmpeg renders the animation. Please be patient!"); -IMGUI_ITEM(IMGUI_RENDERING_ANIMATION_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel rendering the animation.", - self.rowCount = 1 -); - -IMGUI_ITEM(IMGUI_PLAYBACK, - self.label = "&Playback", - self.tooltip = "Opens the playback menu, for configuring playback settings.", - self.popup = "## Playback Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ALWAYS_LOOP, - self.label = "&Always Loop", - self.tooltip = "Sets the animation playback to always loop, regardless of the animation's loop setting.", - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_CLAMP_PLAYHEAD, - self.label = "&Clamp Playhead", - self.tooltip = "The playhead (draggable icon on timeline) won't be able to exceed the animation length.", - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_SETTINGS, - self.label = "&Settings", - self.tooltip = "Opens the setting menu, for configuring general program settings.", - self.popup = "## Settings Popup", - self.popupType = IMGUI_POPUP_BY_ITEM, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_VSYNC, - self.label = "&Vsync", - self.tooltip = "Toggle vertical sync; synchronizes program framerate with your monitor's refresh rate.", - self.isSizeToText = true, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_HOTKEYS, - self.label = "&Hotkeys", - self.tooltip = "Change the program's hotkeys.", - self.popup = "Hotkeys", - self.popupSize = {500, 405}, - self.isSizeToText = true, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_HOTKEYS_CHILD, - self.label = "## Hotkeys Child", - self.size = {IMGUI_HOTKEYS.popupSize.x, IMGUI_HOTKEYS.popupSize.y - 35}, - self.flags = true -); - -#define IMGUI_HOTKEYS_FUNCTION "Function" -#define IMGUI_HOTKEYS_HOTKEY "Hotkey" -IMGUI_ITEM(IMGUI_HOTKEYS_TABLE, - self.label = "## Hotkeys Table", - self.value = 2, - self.flags = ImGuiTableFlags_Borders -); - -IMGUI_ITEM(IMGUI_HOTKEYS_OPTIONS_CHILD, - self.label = "## Merge Options Child", - self.size = {IMGUI_HOTKEYS.popupSize.x, 35}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_HOTKEYS_CONFIRM, - self.label = "Confirm", - self.tooltip = "Use these hotkeys.", - self.rowCount = 1 -); - -IMGUI_ITEM(IMGUI_DEFAULT_SETTINGS, - self.label = "&Reset to Default Settings", - self.tooltip = "Reset the program's settings to their default state.", - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_LAYERS, - self.label = "Layers", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); -IMGUI_ITEM(IMGUI_LAYERS_CHILD, self.label = "## Layers Child", self.flags = true); - -IMGUI_ITEM(IMGUI_LAYER, - self.label = "## Layer Item", - self.dragDrop = "## Layer Drag Drop", - self.atlas = ATLAS_LAYER, - self.idOffset = 3000 -); - -IMGUI_ITEM(IMGUI_LAYER_SPRITESHEET_ID, - self.label = "## Spritesheet ID", - self.tooltip = "Change the spritesheet ID this layer uses.", - self.atlas = ATLAS_SPRITESHEET, - self.size = {50, 0} -); - -#define IMGUI_LAYERS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_LAYER_ADD, - self.label = "Add", - self.tooltip = "Adds a new layer.", - self.snapshotAction = "Add Layer", - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_LAYER_REMOVE, - self.label = "Remove", - self.tooltip = "Removes the selected layer.\nThis will remove all layer animations that use this layer from all animations.", - self.snapshotAction = "Remove Layer", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_LAYERS.label, - self.rowCount = IMGUI_LAYERS_OPTIONS_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_NULLS, - self.label = "Nulls", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); -IMGUI_ITEM(IMGUI_NULLS_CHILD, self.label = "## Nulls Child", self.flags = true); - -IMGUI_ITEM(IMGUI_NULL, - self.label = "## Null Item", - self.dragDrop = "## Null Drag Drop", - self.atlas = ATLAS_NULL, - self.idOffset = 4000 -); - -#define IMGUI_NULLS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_NULL_ADD, - self.label = "Add", - self.tooltip = "Adds a null layer.", - self.snapshotAction = "Add Null", - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_NULL_REMOVE, - self.label = "Remove", - self.tooltip = "Removes the selected null.\nThis will remove all null animations that use this null from all animations.", - self.snapshotAction = "Remove Null", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_NULLS.label, - self.rowCount = IMGUI_NULLS_OPTIONS_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_ANIMATIONS, - self.label = "Animations", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); -IMGUI_ITEM(IMGUI_ANIMATIONS_CHILD, self.label = "## Animations Child", self.flags = true); - -IMGUI_ITEM(IMGUI_ANIMATION, - self.label = "## Animation Item", - self.dragDrop = "## Animation Drag Drop", - self.atlas = ATLAS_ANIMATION, - self.idOffset = 2000 -); - -#define IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT 5 -IMGUI_ITEM(IMGUI_ANIMATION_ADD, - self.label = "Add", - self.tooltip = "Adds a new animation.", - self.snapshotAction = "Add Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_DUPLICATE, - self.label = "Duplicate", - self.tooltip = "Duplicates the selected animation, placing it after.", - self.snapshotAction = "Duplicate Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_MERGE, - self.label = "Merge", - self.tooltip = "Open the animation merge popup, to merge animations together.", - self.popup = "Merge Animations", - self.popupSize = {300, 400}, - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_MERGE_ANIMATIONS_CHILD, - self.label = "## Merge Animations", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 250}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT_CHILD, - self.label = "## Merge On Conflict Child", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 75}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_MERGE_ON_CONFLICT, self.label = "On Conflict"); - -IMGUI_ITEM(IMGUI_MERGE_APPEND_FRAMES, - self.label = "Append Frames ", - self.tooltip = "On frame conflict, the merged animation will have the selected animations' frames appended.", - self.value = ANM2_MERGE_APPEND, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_MERGE_REPLACE_FRAMES, - self.label = "Replace Frames", - self.tooltip = "On frame conflict, the merged animation will have the latest selected animations' frames.", - self.value = ANM2_MERGE_REPLACE -); - -IMGUI_ITEM(IMGUI_MERGE_PREPEND_FRAMES, - self.label = "Prepend Frames", - self.tooltip = "On frame conflict, the merged animation will have the selected animations' frames prepended.", - self.value = ANM2_MERGE_PREPEND, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_MERGE_IGNORE, - self.label = "Ignore ", - self.tooltip = "On frame conflict, the merged animation will ignore the other selected animations' frames.", - self.value = ANM2_MERGE_IGNORE -); - -IMGUI_ITEM(IMGUI_MERGE_OPTIONS_CHILD, - self.label = "## Merge Options Child", - self.size = {IMGUI_ANIMATION_MERGE.popupSize.x, 35}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_MERGE_DELETE_ANIMATIONS_AFTER, - self.label = "Delete Animations After Merging", - self.tooltip = "After merging, the selected animations (besides the original) will be deleted." -); - -IMGUI_ITEM(IMGUI_MERGE_CONFIRM, - self.label = "Merge", - self.tooltip = "Merge the selected animations with the options set.", - self.snapshotAction = "Merge Animations", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_REMOVE, - self.label = "Remove", - self.tooltip = "Remove the selected animation.", - self.snapshotAction = "Remove Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_ANIMATIONS.label, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_DEFAULT, - self.label = "Default", - self.tooltip = "Set the selected animation as the default one.", - self.snapshotAction = "Default Animation", - self.rowCount = IMGUI_ANIMATIONS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_EVENTS, - self.label = "Events", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_EVENTS_CHILD, self.label = "## Events Child", self.flags = true); - -IMGUI_ITEM(IMGUI_EVENT, - self.label = "## Event", - self.atlas = ATLAS_EVENT, - self.idOffset = 1000 -); - -#define IMGUI_EVENTS_OPTIONS_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_EVENTS_ADD, - self.label = "Add", - self.tooltip = "Adds a new event.", - self.snapshotAction = "Add Event", - self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_EVENTS_REMOVE_UNUSED, - self.label = "Remove Unused", - self.tooltip = "Removes all unused events (i.e., not being used in any triggers in any animation).", - self.snapshotAction = "Remove Unused Events", - self.rowCount = IMGUI_EVENTS_OPTIONS_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS, - self.label = "Spritesheets", - self.flags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_CHILD, self.label = "## Spritesheets Child", self.flags = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET_CHILD, - self.label = "## Spritesheet Child", - self.rowCount = 1, - self.size = {0, IMGUI_SPRITESHEET_PREVIEW_SIZE.y + 40}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEET_SELECTED, self.label = "## Spritesheet Selected", self.isSameLine = true); - -IMGUI_ITEM(IMGUI_SPRITESHEET, - self.label = "## Spritesheet", - self.dragDrop = "## Spritesheet Drag Drop", - self.atlas = ATLAS_SPRITESHEET, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_FOOTER_CHILD, - self.label = "## Spritesheets Footer Child", - self.size = {0, 60}, - self.flags = true -); - -#define IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT 4 -#define IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT 3 -IMGUI_ITEM(IMGUI_SPRITESHEET_ADD, - self.label = "Add", - self.tooltip = "Select a .png image to add as a spritesheet.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_RELOAD, - self.label = "Reload", - self.tooltip = "Reload the selected spritesheet(s).", - self.snapshotAction = "Reload Spritesheet(s)", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_REPLACE, - self.label = "Replace", - self.tooltip = "Replace the highlighted spritesheet with another.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_REMOVE_UNUSED, - self.label = "Remove Unused", - self.tooltip = "Remove all unused spritesheets in the anm2 (i.e., no layer in any animation uses the spritesheet).", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_FIRST_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_ALL, - self.label = "Select All", - self.tooltip = "Select all spritesheets.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEETS_SELECT_NONE, - self.label = "Select None", - self.tooltip = "Unselect all spritesheets.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEET_SAVE, - self.label = "Save", - self.tooltip = "Save the selected spritesheets to their original locations.", - self.rowCount = IMGUI_SPRITESHEETS_OPTIONS_SECOND_ROW_COUNT -); - -const ImVec2 IMGUI_CANVAS_CHILD_SIZE = {230, 85}; -IMGUI_ITEM(IMGUI_CANVAS_GRID_CHILD, - self.label = "## Canvas Grid Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_CANVAS_GRID, - self.label = "Grid", - self.tooltip = "Toggles the visiblity of the canvas' grid." -); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_SNAP, - self.label = "Snap", - self.tooltip = "Using the crop tool will snap the points to the nearest grid point." -); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_COLOR, - self.label = "Color", - self.tooltip = "Change the color of the canvas' grid.", - self.flags = ImGuiColorEditFlags_NoInputs -); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_SIZE, - self.label = "Size", - self.tooltip = "Change the size of the canvas' grid.", - self.min = CANVAS_GRID_MIN, - self.max = CANVAS_GRID_MAX, - self.value = CANVAS_GRID_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_GRID_OFFSET, - self.label = "Offset", - self.tooltip = "Change the offset of the canvas' grid, in pixels." -); - -IMGUI_ITEM(IMGUI_CANVAS_VIEW_CHILD, - self.label = "## View Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_CANVAS_ZOOM, - self.label = "Zoom", - self.tooltip = "Change the zoom of the canvas.", - self.min = CANVAS_ZOOM_MIN, - self.max = CANVAS_ZOOM_MAX, - self.speed = 1.0f, - self.value = CANVAS_ZOOM_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_VISUAL_CHILD, - self.label = "## Animation Preview Visual Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_CANVAS_BACKGROUND_COLOR, - self.label = "Background Color", - self.tooltip = "Change the background color of the canvas.", - self.flags = ImGuiColorEditFlags_NoInputs -); - -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY, - self.label = "Overlay", - self.tooltip = "Choose an animation to overlay over the previewed animation, for reference." -); - -IMGUI_ITEM(IMGUI_CANVAS_ANIMATION_OVERLAY_TRANSPARENCY, - self.label = "Alpha", - self.tooltip = "Set the transparency of the animation overlay.", - self.value = SETTINGS_PREVIEW_OVERLAY_TRANSPARENCY_DEFAULT, - self.max = UCHAR_MAX -); - -IMGUI_ITEM(IMGUI_CANVAS_HELPER_CHILD, - self.label = "## Animation Preview Helper Child", - self.size = IMGUI_CANVAS_CHILD_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_CANVAS_AXES, - self.label = "Axes", - self.tooltip = "Toggle the display of the X/Y axes." -); - -IMGUI_ITEM(IMGUI_CANVAS_AXES_COLOR, - self.label = "Color", - self.tooltip = "Change the color of the axes.", - self.flags = ImGuiColorEditFlags_NoInputs -); - -IMGUI_ITEM(IMGUI_CANVAS_ROOT_TRANSFORM, - self.label = "Root Transform", - self.tooltip = "Toggles the root frames's attributes transforming the other items in an animation.", - self.value = SETTINGS_PREVIEW_IS_ROOT_TRANSFORM_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_TRIGGERS, - self.label = "Triggers", - self.tooltip = "Toggles activated triggers drawing their event name.", - self.value = SETTINGS_PREVIEW_IS_TRIGGERS_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_PIVOTS, - self.label = "Pivots", - self.tooltip = "Toggles drawing each layer's pivot.", - self.value = SETTINGS_PREVIEW_IS_PIVOTS_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_ICONS, - self.label = "Icons", - self.tooltip = "Toggles drawing the the colored root/null icons.", - self.value = SETTINGS_PREVIEW_IS_ICONS_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_ALT_ICONS, - self.label = "Alt Icons", - self.tooltip = "Toggles the use of alternate icons for the targets (the colored root/null icons).", - self.value = SETTINGS_PREVIEW_IS_ALT_ICONS_DEFAULT -); - -IMGUI_ITEM(IMGUI_CANVAS_BORDER, - self.label = "Border", - self.tooltip = "Toggles the appearance of a border around the items.", - self.value = SETTINGS_PREVIEW_IS_BORDER_DEFAULT -); - -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW, - self.label = "Animation Preview", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -#define IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_CENTER_VIEW, - self.label = "Center View", - self.tooltip = "Centers the current view on the animation preview.", - self.hotkey = HOTKEY_CENTER_VIEW, - self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, - self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_PREVIEW_FIT, - self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the animation, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, - self.focusWindow = IMGUI_ANIMATION_PREVIEW.label, - self.rowCount = IMGUI_ANIMATION_PREVIEW_VIEW_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR, - self.label = "Spritesheet Editor", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -#define IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW, - self.label = "Center View", - self.tooltip = "Centers the current view on the spritesheet editor.", - self.hotkey = HOTKEY_CENTER_VIEW, - self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, - self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_SPRITESHEET_EDITOR_FIT, - self.label = "Fit", - self.tooltip = "Adjust the view/pan based on the size of the spritesheet, to fit the canvas' size.", - self.hotkey = HOTKEY_FIT, - self.focusWindow = IMGUI_SPRITESHEET_EDITOR.label, - self.rowCount = IMGUI_SPRITESHEET_EDITOR_VIEW_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES, self.label = "Frame Properties"); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_POSITION, - self.label = "Position", - self.tooltip = "Change the position of the selected frame.", - self.snapshotAction = "Frame Position", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_CROP, - self.label = "Crop", - self.tooltip = "Change the crop position of the selected frame.", - self.snapshotAction = "Frame Crop", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SIZE, - self.label = "Size", - self.tooltip = "Change the size of the crop of the selected frame.", - self.snapshotAction = "Frame Size", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_PIVOT, - self.label = "Pivot", - self.tooltip = "Change the pivot of the selected frame.", - self.snapshotAction = "Frame Pivot", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_SCALE, - self.label = "Scale", - self.tooltip = "Change the scale of the selected frame.", - self.snapshotAction = "Frame Scale", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROTATION, - self.label = "Rotation", - self.tooltip = "Change the rotation of the selected frame.", - self.snapshotAction = "Frame Rotation", - self.isUseItemActivated = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_DELAY, - self.label = "Duration", - self.tooltip = "Change the duration of the selected frame.", - self.snapshotAction = "Frame Duration", - self.isUseItemActivated = true, - self.min = ANM2_FRAME_NUM_MIN, - self.max = ANM2_FRAME_NUM_MAX, - self.value = ANM2_FRAME_NUM_MIN -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_TINT, - self.label = "Tint", - self.tooltip = "Change the tint of the selected frame.", - self.snapshotAction = "Frame Tint", - self.isUseItemActivated = true, - self.value = 1 -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_COLOR_OFFSET, - self.label = "Color Offset", - self.tooltip = "Change the color offset of the selected frame.", - self.snapshotAction = "Frame Color Offset", - self.isUseItemActivated = true, - self.value = 0 -); - -#define IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_X, - self.label = "Flip X", - self.tooltip = "Change the sign of the X scale, to cheat flipping the layer horizontally.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip X", - self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_FLIP_Y, - self.label = "Flip Y", - self.tooltip = "Change the sign of the Y scale, to cheat flipping the layer vertically.\n(Anm2 doesn't support flipping directly.)", - self.snapshotAction = "Frame Flip Y", - self.rowCount = IMGUI_FRAME_PROPERTIES_FLIP_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_VISIBLE, - self.label = "Visible", - self.tooltip = "Toggles the visibility of the selected frame.", - self.snapshotAction = "Frame Visibility", - self.isSameLine = true, - self.value = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_INTERPOLATED, - self.label = "Interpolation", - self.tooltip = "Toggles the interpolation of the selected frame.", - self.snapshotAction = "Frame Interpolation", - self.isSameLine = true, - self.value = true -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_ROUND, - self.label = "Round", - self.tooltip = "Values will be rounded to the nearest integer.", - self.value = SETTINGS_PROPERTIES_IS_ROUND_DEFAULT -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_EVENT, - self.label = "Event", - self.tooltip = "Change the event the trigger uses.", - self.snapshotAction = "Trigger Event" -); - -IMGUI_ITEM(IMGUI_FRAME_PROPERTIES_AT_FRAME, - self.label = "At Frame", - self.tooltip = "Change the frame where the trigger occurs.", - self.snapshotAction = "Trigger At Frame" -); - -IMGUI_ITEM(IMGUI_TOOLS, self.label = "Tools"); - -IMGUI_ITEM(IMGUI_TOOL_PAN, - self.label = "## Pan", - self.tooltip = "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to pan at any time.", - self.function = imgui_tool_pan_set, - self.hotkey = HOTKEY_PAN, - self.atlas = ATLAS_PAN -); - -IMGUI_ITEM(IMGUI_TOOL_MOVE, - self.label = "## Move", - self.tooltip = "Use the move tool.\nWhen in animation preview, will move the position of the frame.\nWhen in spritesheet editor, will move the pivot instead.\nUse mouse or directional keys to change the value.", - self.function = imgui_tool_move_set, - self.hotkey = HOTKEY_MOVE, - self.atlas = ATLAS_MOVE -); - -IMGUI_ITEM(IMGUI_TOOL_ROTATE, - self.label = "## Rotate", - self.tooltip = "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_rotate_set, - self.hotkey = HOTKEY_ROTATE, - self.atlas = ATLAS_ROTATE -); - -IMGUI_ITEM(IMGUI_TOOL_SCALE, - self.label = "## Scale", - self.tooltip = "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are pressed.\n(Animation Preview only.)", - self.function = imgui_tool_scale_set, - self.hotkey = HOTKEY_SCALE, - self.atlas = ATLAS_SCALE -); - -IMGUI_ITEM(IMGUI_TOOL_CROP, - self.label = "## Crop", - self.tooltip = "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged.\nAlternatively, you can use the arrow keys and Ctrl/Shift to move the size/position, respectively.\n(Spritesheet Editor only.)", - self.function = imgui_tool_crop_set, - self.hotkey = HOTKEY_CROP, - self.atlas = ATLAS_CROP -); - -IMGUI_ITEM(IMGUI_TOOL_DRAW, - self.label = "## Draw", - self.tooltip = "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)", - self.function = imgui_tool_draw_set, - self.hotkey = HOTKEY_DRAW, - self.atlas = ATLAS_DRAW -); - -IMGUI_ITEM(IMGUI_TOOL_ERASE, - self.label = "## Erase", - self.tooltip = "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)", - self.function = imgui_tool_erase_set, - self.hotkey = HOTKEY_ERASE, - self.atlas = ATLAS_ERASE -); - -IMGUI_ITEM(IMGUI_TOOL_COLOR_PICKER, - self.label = "## Color Picker", - self.tooltip = "Selects a color from the canvas, to be used for drawing.\n(Spritesheet Editor only).", - self.function = imgui_tool_color_picker_set, - self.hotkey = HOTKEY_COLOR_PICKER, - self.atlas = ATLAS_COLOR_PICKER -); - -IMGUI_ITEM(IMGUI_TOOL_UNDO, - self.label = "## Undo", - self.tooltip = "Undo the last action.", - self.function = imgui_undo, - self.hotkey = HOTKEY_UNDO, - self.atlas = ATLAS_UNDO -); - -IMGUI_ITEM(IMGUI_TOOL_REDO, - self.label = "## Redo", - self.tooltip = "Redo the last action.", - self.function = imgui_redo, - self.hotkey = HOTKEY_REDO, - self.atlas = ATLAS_REDO -); - -IMGUI_ITEM(IMGUI_TOOL_COLOR, - self.label = "## Color", - self.tooltip = "Set the color, to be used by the draw tool.", - self.flags = ImGuiColorEditFlags_NoInputs -); - -const inline ImguiItem* IMGUI_TOOL_ITEMS[TOOL_COUNT] = -{ - &IMGUI_TOOL_PAN, - &IMGUI_TOOL_MOVE, - &IMGUI_TOOL_ROTATE, - &IMGUI_TOOL_SCALE, - &IMGUI_TOOL_CROP, - &IMGUI_TOOL_DRAW, - &IMGUI_TOOL_ERASE, - &IMGUI_TOOL_COLOR_PICKER, - &IMGUI_TOOL_UNDO, - &IMGUI_TOOL_REDO, - &IMGUI_TOOL_COLOR -}; - -IMGUI_ITEM(IMGUI_COLOR_PICKER_BUTTON, self.label = "## Color Picker Button"); - -IMGUI_ITEM(IMGUI_TIMELINE, - self.label = "Timeline", - self.flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_CHILD, - self.label = "## Timeline Child", - self.flags = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_HEADER_CHILD, - self.label = "## Timeline Header Child", - self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_PLAYHEAD, - self.label = "## Playhead", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoBackground | - ImGuiWindowFlags_NoInputs -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEMS_CHILD, - self.label = "## Timeline Items", - self.size = {IMGUI_TIMELINE_ITEM_SIZE.x, 0}, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_CHILD, - self.label = "## Timeline Item Child", - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_CHILD, - self.label = "## Root Item Child", - self.color = {{0.045f, 0.08f, 0.11f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_CHILD, - self.label = "## Layer Item Child", - self.color = {{0.0875f, 0.05f, 0.015f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_CHILD, - self.label = "## Null Item Child", - self.color = {{0.055f, 0.10f, 0.055f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD, - self.label = "## Triggers Item Child", - self.color = {{0.10f, 0.0375f, 0.07f, 1.0f}}, - self.size = IMGUI_TIMELINE_ITEM_SIZE, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse -); - -const inline ImguiItem* IMGUI_TIMELINE_ITEM_CHILDS[ANM2_COUNT] -{ - &IMGUI_TIMELINE_ITEM_CHILD, - &IMGUI_TIMELINE_ITEM_ROOT_CHILD, - &IMGUI_TIMELINE_ITEM_LAYER_CHILD, - &IMGUI_TIMELINE_ITEM_NULL_CHILD, - &IMGUI_TIMELINE_ITEM_TRIGGERS_CHILD -}; - -#define IMGUI_POPUP_ITEM_PROPERTIES "Item Properties" -#define IMGUI_POPUP_ITEM_PROPERTIES_TYPE IMGUI_POPUP_CENTER_WINDOW -const ImVec2 IMGUI_POPUP_ITEM_PROPERTIES_SIZE = {300, 350}; - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_TYPE_CHILD, - self.label = "## Item Properties Type Child", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_LAYER, - self.label = "Layer", - self.tooltip = "The item will be a layer item.\nA layer item is a primary graphical item, using a spritesheet.", - self.isSizeToText = true, - self.value = ANM2_LAYER, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_NULL, - self.label = "Null", - self.tooltip = "The item will be a null item.\nA null item is an invisible item, often accessed by a game engine.", - self.isSizeToText = true, - self.value = ANM2_NULL -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_ITEMS_CHILD, - self.label = "## Item Properties Items", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 250}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_OPTIONS_CHILD, - self.label = "## Item Properties Options Child", - self.size = {IMGUI_POPUP_ITEM_PROPERTIES_SIZE.x, 35}, - self.flags = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_PROPERTIES_CONFIRM, - self.label = "Confirm", - self.tooltip = "Set the timeline item's properties.", - self.snapshotAction = "Timeline Item Change", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SELECTABLE, - self.label = "## Selectable", - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, - self.label = "Root", - self.tooltip = "The root item of an animation.\nChanging its properties will transform the rest of the animation.", - self.atlas = ATLAS_ROOT, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, - self.label = "## Layer Selectable", - self.tooltip = "A layer item.\nA graphical item within the animation.", - self.dragDrop = "## Layer Drag Drop", - self.popup = IMGUI_POPUP_ITEM_PROPERTIES, - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.atlas = ATLAS_LAYER, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, - self.label = "## Null Selectable", - self.tooltip = "A null item.\nAn invisible item within the animation that is accessible via a game engine.", - self.dragDrop = "## Null Drag Drop", - self.popup = IMGUI_POPUP_ITEM_PROPERTIES, - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.atlas = ATLAS_NULL, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE, - self.label = "Triggers", - self.tooltip = "The animation's triggers.\nWill fire based on an event.", - self.atlas = ATLAS_TRIGGERS, - self.size = IMGUI_TIMELINE_ITEM_SELECTABLE_SIZE -); - -const inline ImguiItem* IMGUI_TIMELINE_ITEM_SELECTABLES[ANM2_COUNT] -{ - &IMGUI_TIMELINE_ITEM_SELECTABLE, - &IMGUI_TIMELINE_ITEM_ROOT_SELECTABLE, - &IMGUI_TIMELINE_ITEM_LAYER_SELECTABLE, - &IMGUI_TIMELINE_ITEM_NULL_SELECTABLE, - &IMGUI_TIMELINE_ITEM_TRIGGERS_SELECTABLE -}; - -IMGUI_ITEM(IMGUI_TIMELINE_SHOW_UNUSED, - self.label = "## Show Unused", - self.tooltip = "Layers/nulls without any frames will be hidden.", - self.snapshotAction = "Hide Unused", - self.atlas = ATLAS_SHOW_UNUSED -); - -IMGUI_ITEM(IMGUI_TIMELINE_HIDE_UNUSED, - self.label = "## Hide Unused", - self.tooltip = "Layers/nulls without any frames will be shown.", - self.snapshotAction = "Show Unused", - self.atlas = ATLAS_HIDE_UNUSED -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_VISIBLE, - self.label = "## Visible", - self.tooltip = "The item is visible.\nPress to set to invisible.", - self.snapshotAction = "Item Invisible", - self.atlas = ATLAS_VISIBLE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_INVISIBLE, - self.label = "## Invisible", - self.tooltip = "The item is invisible.\nPress to set to visible.", - self.snapshotAction = "Item Visible", - self.atlas = ATLAS_INVISIBLE -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_SHOW_RECT, - self.label = "## Show Rect", - self.tooltip = "The rect is shown.\nPress to hide rect.", - self.snapshotAction = "Hide Rect", - self.atlas = ATLAS_SHOW_RECT -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_HIDE_RECT, - self.label = "## Hide Rect", - self.tooltip = "The rect is hidden.\nPress to show rect.", - self.snapshotAction = "Show Rect", - self.atlas = ATLAS_HIDE_RECT -); - - -IMGUI_ITEM(IMGUI_TIMELINE_FRAMES_CHILD, - self.label = "## Timeline Frames Child", - self.windowFlags = ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_HorizontalScrollbar -); - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FRAMES_CHILD, - self.label = "## Timeline Item Frames Child", - self.size = {0, IMGUI_TIMELINE_FRAME_SIZE.y} -); - -IMGUI_ITEM(IMGUI_TIMELINE_FRAME, self.label = "## Frame"); - -#define IMGUI_TIMELINE_FRAME_BORDER 5 -static const vec4 IMGUI_FRAME_BORDER_COLOR = {1.0f, 1.0f, 1.0f, 0.25f}; -IMGUI_ITEM(IMGUI_TIMELINE_ROOT_FRAME, - self.label = "## Root Frame", - self.snapshotAction = "Root Frame", - self.color = {{0.14f, 0.27f, 0.39f, 1.0f}, {0.28f, 0.54f, 0.78f, 1.0f}, {0.36f, 0.70f, 0.95f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); - -IMGUI_ITEM(IMGUI_TIMELINE_LAYER_FRAME, - self.label = "## Layer Frame", - self.dragDrop = "## Layer Frame Drag Drop", - self.snapshotAction = "Layer Frame", - self.color = {{0.45f, 0.18f, 0.07f, 1.0f}, {0.78f, 0.32f, 0.12f, 1.0f}, {0.95f, 0.40f, 0.15f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); - -IMGUI_ITEM(IMGUI_TIMELINE_NULL_FRAME, - self.label = "## Null Frame", - self.dragDrop = "## Null Frame Drag Drop", - self.snapshotAction = "Null Frame", - self.color = {{0.17f, 0.33f, 0.17f, 1.0f}, {0.34f, 0.68f, 0.34f, 1.0f}, {0.44f, 0.88f, 0.44f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); - -IMGUI_ITEM(IMGUI_TIMELINE_TRIGGERS_FRAME, - self.label = "## Triggers Frame", - self.snapshotAction = "Trigger", - self.color = {{0.36f, 0.14f, 0.24f, 1.0f}, {0.72f, 0.28f, 0.48f, 1.0f}, {0.92f, 0.36f, 0.60f, 1.0f}, IMGUI_FRAME_BORDER_COLOR}, - self.size = IMGUI_TIMELINE_FRAME_SIZE, - self.atlasOffset = IMGUI_TIMELINE_FRAME_ATLAS_OFFSET, - self.border = IMGUI_FRAME_BORDER -); - -const inline ImguiItem* IMGUI_TIMELINE_FRAMES[ANM2_COUNT] -{ - &IMGUI_TIMELINE_FRAME, - &IMGUI_TIMELINE_ROOT_FRAME, - &IMGUI_TIMELINE_LAYER_FRAME, - &IMGUI_TIMELINE_NULL_FRAME, - &IMGUI_TIMELINE_TRIGGERS_FRAME -}; - -IMGUI_ITEM(IMGUI_TIMELINE_ITEM_FOOTER_CHILD, - self.label = "## Item Footer Child", - self.size = {IMGUI_TIMELINE_ITEM_CHILD.size.x, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); -IMGUI_ITEM(IMGUI_TIMELINE_OPTIONS_FOOTER_CHILD, - self.label = "## Options Footer Child", - self.size = {0, IMGUI_FOOTER_CHILD.size.y}, - self.flags = true, - self.windowFlags = ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoScrollWithMouse -); - -#define IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT 2 -IMGUI_ITEM(IMGUI_TIMELINE_ADD_ITEM, - self.label = "Add", - self.tooltip = "Adds an item (layer or null) to the animation.\nMake sure to add a Layer/Null first in the Layers or Nulls windows.", - self.popup = "Add Item", - self.popupType = IMGUI_POPUP_ITEM_PROPERTIES_TYPE, - self.popupSize = {300, 350}, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT, - self.isSameLine = true -); - - - -IMGUI_ITEM(IMGUI_TIMELINE_REMOVE_ITEM, - self.label = "Remove", - self.tooltip = "Removes the selected item (layer or null) from the animation.", - self.snapshotAction = "Remove Item", - self.chord = ImGuiKey_Delete, - self.focusWindow = IMGUI_TIMELINE_ITEMS_CHILD.label, - self.rowCount = IMGUI_TIMELINE_FOOTER_ITEM_CHILD_ITEM_COUNT -); - -#define IMGUI_TIMELINE_OPTIONS_ROW_COUNT 10 -IMGUI_ITEM(IMGUI_PLAY, - self.label = "|> Play", - self.tooltip = "Play the current animation, if paused.", - self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_PAUSE, - self.label = "|| Pause", - self.tooltip = "Pause the current animation, if playing.", - self.focusWindow = IMGUI_TIMELINE.label, - self.hotkey = HOTKEY_PLAY_PAUSE, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ADD_FRAME, - self.label = "+ Insert Frame", - self.tooltip = "Inserts a frame in the selected animation item, based on the preview time.", - self.snapshotAction = "Insert Frame", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_REMOVE_FRAME, - self.label = "- Delete Frame", - self.tooltip = "Removes the selected frame from the selected animation item.", - self.snapshotAction = "Delete Frame", - self.focusWindow = IMGUI_TIMELINE.label, - self.chord = ImGuiKey_Delete, - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_BAKE, - self.label = "Bake", - self.tooltip = "Opens the bake popup menu, if a frame is selected.\nBaking a frame takes the currently interpolated values at the time between it and the next frame and separates them based on the interval.", - self.popup = "Bake Frames", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.popupSize = {260, 145}, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_BAKE_CHILD, - self.label = "## Bake Child", - self.flags = true -); - -IMGUI_ITEM(IMGUI_BAKE_INTERVAL, - self.label = "Interval", - self.tooltip = "Sets the delay of the baked frames the selected frame will be separated out into.", - self.min = ANM2_FRAME_DELAY_MIN, - self.value = ANM2_FRAME_DELAY_MIN -); - -IMGUI_ITEM(IMGUI_BAKE_ROUND_SCALE, - self.label = "Round Scale", - self.tooltip = "The scale of the baked frames will be rounded to the nearest integer.", - self.value = true -); - -IMGUI_ITEM(IMGUI_BAKE_ROUND_ROTATION, - self.label = "Round Rotation", - self.tooltip = "The rotation of the baked frames will be rounded to the nearest integer.", - self.value = true, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_BAKE_CONFIRM, - self.label = "Bake", - self.tooltip = "Bake the selected frame with the options selected.", - self.snapshotAction = "Bake Frames", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_FIT_ANIMATION_LENGTH, - self.label = "Fit Animation Length", - self.tooltip = "Sets the animation's length to the latest frame.", - self.snapshotAction = "Fit Animation Length", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ANIMATION_LENGTH, - self.label = "Length", - self.tooltip = "Sets the animation length.\n(Will not change frames.)", - self.snapshotAction = "Set Animation Length", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.min = ANM2_FRAME_NUM_MIN, - self.max = ANM2_FRAME_NUM_MAX, - self.value = ANM2_FRAME_NUM_MIN, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_FPS, - self.label = "FPS", - self.tooltip = "Sets the animation's frames per second (its speed).", - self.snapshotAction = "Set FPS", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.min = ANM2_FPS_MIN, - self.max = ANM2_FPS_MAX, - self.value = ANM2_FPS_DEFAULT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_LOOP, - self.label = "Loop", - self.tooltip = "Toggles the animation looping.", - self.snapshotAction = "Set Loop", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.value = true, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_CREATED_BY, - self.label = "Author", - self.tooltip = "Sets the author of the animation.", - self.rowCount = IMGUI_TIMELINE_OPTIONS_ROW_COUNT, - self.max = UCHAR_MAX -); - -#define IMGUI_ONIONSKIN_ROW_COUNT 3 -IMGUI_ITEM(IMGUI_ONIONSKIN, self.label = "Onionskin"); -IMGUI_ITEM(IMGUI_ONIONSKIN_ENABLED, - self.label = "Enabled", - self.tooltip = "Toggle onionskin (previews of frames before/after the current one.)", - self.function = imgui_onionskin_toggle, - self.hotkey = HOTKEY_ONIONSKIN, - self.isSeparator = true -); - -IMGUI_ITEM(IMGUI_ONIONSKIN_BEFORE, self.label = "-- Before -- "); -IMGUI_ITEM(IMGUI_ONIONSKIN_AFTER, self.label = "-- After -- "); - -IMGUI_ITEM(IMGUI_ONIONSKIN_COUNT, - self.label = "Count", - self.tooltip = "Set the number of previewed frames appearing.", - self.min = 0, - self.max = 100, - self.value = SETTINGS_ONIONSKIN_BEFORE_COUNT_DEFAULT, - self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ONIONSKIN_COLOR_OFFSET, - self.label = "Color Offset", - self.tooltip = "Set the color offset of the previewed frames.", - self.flags = ImGuiColorEditFlags_NoInputs, - self.rowCount = IMGUI_ONIONSKIN_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_ONIONSKIN_DRAW_ORDER, - self.label = "Draw Order", - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ONIONSKIN_BELOW, - self.label = "Below", - self.tooltip = "The onionskin frames will draw below the base frame.", - self.value = ONIONSKIN_BELOW, - self.isSameLine = true -); - -IMGUI_ITEM(IMGUI_ONIONSKIN_ABOVE, - self.label = "Above", - self.tooltip = "The onionskin frames will draw above the base frame.", - self.value = ONIONSKIN_ABOVE -); - -IMGUI_ITEM(IMGUI_CONTEXT_MENU, self.label = "## Context Menu"); - -IMGUI_ITEM(IMGUI_CUT, - self.label = "Cut", - self.tooltip = "Cuts the currently selected contextual element; removing it and putting it to the clipboard.", - self.snapshotAction = "Cut", - self.function = imgui_cut, - self.hotkey = HOTKEY_CUT, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_COPY, - self.label = "Copy", - self.tooltip = "Copies the currently selected contextual element to the clipboard.", - self.snapshotAction = "Copy", - self.function = imgui_copy, - self.hotkey = HOTKEY_COPY, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_PASTE, - self.label = "Paste", - self.tooltip = "Pastes the currently selection contextual element from the clipboard.", - self.snapshotAction = "Paste", - self.function = imgui_paste, - self.hotkey = HOTKEY_PASTE, - self.isSizeToText = true -); - -IMGUI_ITEM(IMGUI_CHANGE_INPUT_TEXT, - self.label = "## Input Text", - self.tooltip = "Rename the selected item.", - self.snapshotAction = "Rename Item", - self.flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue, - self.max = UCHAR_MAX -); - -IMGUI_ITEM(IMGUI_CHANGE_INPUT_INT, - self.label = "## Input Int", - self.tooltip = "Change the selected item's value.", - self.snapshotAction = "Change Value", - self.step = 0 -); - -#define IMGUI_CONFIRM_POPUP_ROW_COUNT 2 -IMGUI_ITEM(IMGUI_POPUP_OK, - self.label = "OK", - self.tooltip = "Confirm the action.", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_POPUP_CANCEL, - self.label = "Cancel", - self.tooltip = "Cancel the action.", - self.rowCount = IMGUI_CONFIRM_POPUP_ROW_COUNT -); - -IMGUI_ITEM(IMGUI_LOG_WINDOW, - self.label = "## Log Window", - self.flags = ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoScrollbar | - ImGuiWindowFlags_NoSavedSettings | - ImGuiWindowFlags_AlwaysAutoResize | - ImGuiWindowFlags_NoFocusOnAppearing | - ImGuiWindowFlags_NoNav | - ImGuiWindowFlags_NoInputs -); - -void imgui_init -( - Imgui* self, - Dialog* dialog, - Resources* resources, - Anm2* anm2, - Anm2Reference* reference, - Editor* editor, - Preview* preview, - GeneratePreview* generatePreview, - Settings* settings, - Snapshots* snapshots, - Clipboard* clipboard, - SDL_Window* window, - SDL_GLContext* glContext -); - -void imgui_update(Imgui* self); -void imgui_draw(); -void imgui_free(); \ No newline at end of file diff --git a/src/imgui/dockspace.cpp b/src/imgui/dockspace.cpp new file mode 100644 index 0000000..4a5a99d --- /dev/null +++ b/src/imgui/dockspace.cpp @@ -0,0 +1,50 @@ +#include "dockspace.h" + +namespace anm2ed::imgui +{ + void Dockspace::tick(Manager& manager, Settings& settings) + { + if (auto document = manager.get(); document) + if (settings.windowIsAnimationPreview) animationPreview.tick(manager, *document, settings); + } + + void Dockspace::update(Taskbar& taskbar, Documents& documents, Manager& manager, Settings& settings, + Resources& resources, Dialog& dialog, Clipboard& clipboard) + { + + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = viewport->Size.y - taskbar.height - documents.height; + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + if (ImGui::Begin("##DockSpace", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus)) + { + if (auto document = manager.get(); document) + { + if (ImGui::DockSpace(ImGui::GetID("##DockSpace"), ImVec2(), ImGuiDockNodeFlags_PassthruCentralNode)) + { + if (settings.windowIsAnimationPreview) animationPreview.update(manager, settings, resources); + if (settings.windowIsAnimations) animations.update(manager, settings, resources, clipboard); + if (settings.windowIsEvents) events.update(manager, settings, resources, clipboard); + if (settings.windowIsFrameProperties) frameProperties.update(manager, settings); + if (settings.windowIsLayers) layers.update(manager, settings, resources, clipboard); + if (settings.windowIsNulls) nulls.update(manager, settings, resources, clipboard); + if (settings.windowIsOnionskin) onionskin.update(settings); + if (settings.windowIsSounds) sounds.update(manager, settings, resources, dialog, clipboard); + if (settings.windowIsSpritesheetEditor) spritesheetEditor.update(manager, settings, resources); + if (settings.windowIsSpritesheets) spritesheets.update(manager, settings, resources, dialog, clipboard); + if (settings.windowIsTimeline) timeline.update(manager, settings, resources, clipboard); + if (settings.windowIsTools) tools.update(manager, settings, resources); + } + } + else + welcome.update(manager, resources, dialog, taskbar, documents); + } + ImGui::End(); + } +} diff --git a/src/imgui/dockspace.h b/src/imgui/dockspace.h new file mode 100644 index 0000000..52cd852 --- /dev/null +++ b/src/imgui/dockspace.h @@ -0,0 +1,41 @@ +#pragma once + +#include "documents.h" +#include "taskbar.h" +#include "window/animation_preview.h" +#include "window/animations.h" +#include "window/events.h" +#include "window/frame_properties.h" +#include "window/layers.h" +#include "window/nulls.h" +#include "window/onionskin.h" +#include "window/sounds.h" +#include "window/spritesheet_editor.h" +#include "window/spritesheets.h" +#include "window/timeline.h" +#include "window/tools.h" +#include "window/welcome.h" + +namespace anm2ed::imgui +{ + class Dockspace + { + AnimationPreview animationPreview; + Animations animations; + Events events; + FrameProperties frameProperties; + Layers layers; + Nulls nulls; + Onionskin onionskin; + SpritesheetEditor spritesheetEditor; + Spritesheets spritesheets; + Sounds sounds; + Timeline timeline; + Tools tools; + Welcome welcome; + + public: + void tick(Manager&, Settings&); + void update(Taskbar&, Documents&, Manager&, Settings&, Resources&, Dialog&, Clipboard&); + }; +} diff --git a/src/imgui/documents.cpp b/src/imgui/documents.cpp new file mode 100644 index 0000000..49b611e --- /dev/null +++ b/src/imgui/documents.cpp @@ -0,0 +1,161 @@ +#include "documents.h" + +#include + +#include "time_.h" + +using namespace anm2ed::resource; +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed::imgui +{ + void Documents::update(Taskbar& taskbar, Manager& manager, Settings& settings, Resources& resources, bool& isQuitting) + { + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = ImGui::GetFrameHeightWithSpacing(); + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + for (auto& document : manager.documents) + { + auto isDirty = document.is_dirty() && document.is_autosave_dirty(); + document.lastAutosaveTime += ImGui::GetIO().DeltaTime; + + if (isDirty && document.lastAutosaveTime > settings.fileAutosaveTime * time::SECOND_M) manager.autosave(document); + } + + if (ImGui::Begin("##Documents", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | + ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse)) + { + height = ImGui::GetWindowSize().y; + + if (ImGui::BeginTabBar("Documents Bar", ImGuiTabBarFlags_Reorderable)) + { + auto documentsCount = (int)manager.documents.size(); + bool closeShortcut = imgui::shortcut(settings.shortcutClose, shortcut::GLOBAL) && !closePopup.is_open(); + int closeShortcutIndex = + closeShortcut && manager.selected >= 0 && manager.selected < documentsCount ? manager.selected : -1; + + std::vector closeIndices{}; + closeIndices.reserve(documentsCount); + + for (int i = 0; i < documentsCount; ++i) + { + auto& document = manager.documents[i]; + auto isDirty = document.is_dirty() || document.isForceDirty; + + if (!closePopup.is_open()) + { + if (isQuitting) + document.isOpen = false; + else if (i == closeShortcutIndex) + document.isOpen = false; + } + + if (!closePopup.is_open() && !document.isOpen) + { + if (isDirty) + { + closePopup.open(); + closeDocumentIndex = i; + document.isOpen = true; + } + else + { + closeIndices.push_back(i); + continue; + } + } + + auto isRequested = i == manager.pendingSelected; + auto font = isDirty ? font::ITALICS : font::REGULAR; + auto string = isDirty ? std::format("[Not Saved] {}", document.filename_get().string()) + : document.filename_get().string(); + auto label = std::format("{}###Document{}", string, i); + + auto flags = isDirty ? ImGuiTabItemFlags_UnsavedDocument : 0; + if (isRequested) flags |= ImGuiTabItemFlags_SetSelected; + + ImGui::PushFont(resources.fonts[font].get(), font::SIZE); + if (ImGui::BeginTabItem(label.c_str(), &document.isOpen, flags)) + { + manager.set(i); + + if (isRequested) manager.pendingSelected = -1; + + ImGui::EndTabItem(); + } + ImGui::PopFont(); + } + + for (auto it = closeIndices.rbegin(); it != closeIndices.rend(); ++it) + { + if (closePopup.is_open() && closeDocumentIndex > *it) --closeDocumentIndex; + manager.close(*it); + } + + ImGui::EndTabBar(); + } + + closePopup.trigger(); + + if (ImGui::BeginPopupModal(closePopup.label, &closePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + if (closeDocumentIndex >= 0 && closeDocumentIndex < (int)manager.documents.size()) + { + auto& closeDocument = manager.documents[closeDocumentIndex]; + + ImGui::TextUnformatted(std::format("The document \"{}\" has been modified.\nDo you want to save it?", + closeDocument.filename_get().string()) + .c_str()); + + auto widgetSize = imgui::widget_size_with_row_get(3); + + auto close = [&]() + { + closeDocumentIndex = -1; + closePopup.close(); + }; + + if (ImGui::Button("Yes", widgetSize)) + { + manager.save(closeDocumentIndex); + manager.close(closeDocumentIndex); + close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("No", widgetSize)) + { + manager.close(closeDocumentIndex); + close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) + { + isQuitting = false; + close(); + } + } + else + { + closeDocumentIndex = -1; + closePopup.close(); + } + + ImGui::EndPopup(); + } + } + + ImGui::End(); + } +} diff --git a/src/imgui/documents.h b/src/imgui/documents.h new file mode 100644 index 0000000..7e9c039 --- /dev/null +++ b/src/imgui/documents.h @@ -0,0 +1,20 @@ +#pragma once + +#include "manager.h" +#include "resources.h" +#include "settings.h" +#include "taskbar.h" + +namespace anm2ed::imgui +{ + class Documents + { + int closeDocumentIndex{-1}; + imgui::PopupHelper closePopup{imgui::PopupHelper("Close Document", imgui::POPUP_TO_CONTENT)}; + + public: + float height{}; + + void update(Taskbar&, Manager&, Settings&, Resources&, bool&); + }; +} diff --git a/src/imgui/imgui_.cpp b/src/imgui/imgui_.cpp new file mode 100644 index 0000000..c761f03 --- /dev/null +++ b/src/imgui/imgui_.cpp @@ -0,0 +1,318 @@ +#include "imgui_.h" + +#include + +#include +#include +#include + +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + int input_text_callback(ImGuiInputTextCallbackData* data) + { + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + auto* string = (std::string*)(data->UserData); + string->resize(data->BufTextLen); + data->Buf = string->data(); + } + return 0; + } + + bool input_text_string(const char* label, std::string* string, ImGuiInputTextFlags flags) + { + flags |= ImGuiInputTextFlags_CallbackResize; + return ImGui::InputText(label, string->data(), string->capacity() + 1, flags, input_text_callback, string); + } + + bool combo_negative_one_indexed(const std::string& label, int* index, std::vector& strings) + { + *index += 1; + bool isActivated = ImGui::Combo(label.c_str(), index, strings.data(), (int)strings.size()); + *index -= 1; + + return isActivated; + } + + bool input_int_range(const char* label, int& value, int min, int max, int step, int stepFast, + ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputInt(label, &value, step, stepFast, flags); + value = glm::clamp(value, min, max); + return isActivated; + } + + bool input_int2_range(const char* label, ivec2& value, ivec2 min, ivec2 max, ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputInt2(label, value_ptr(value), flags); + value = glm::clamp(value, min, max); + return isActivated; + } + + bool input_float_range(const char* label, float& value, float min, float max, float step, float stepFast, + const char* format, ImGuiInputTextFlags flags) + { + auto isActivated = ImGui::InputFloat(label, &value, step, stepFast, format, flags); + value = glm::clamp(value, min, max); + return isActivated; + } + + bool selectable_input_text(const std::string& label, const std::string& id, std::string& text, bool isSelected, + ImGuiSelectableFlags flags, bool* isRenamed) + { + static std::string editID{}; + static bool isJustEdit{}; + const bool isEditing = editID == id; + bool isActivated{}; + + if (isEditing) + { + if (isJustEdit) + { + ImGui::SetKeyboardFocusHere(); + isJustEdit = false; + } + + ImGui::SetNextItemWidth(-FLT_MIN); + if (input_text_string("##Edit", &text, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) + { + editID.clear(); + isActivated = true; + if (isRenamed) *isRenamed = true; + } + if (ImGui::IsItemDeactivatedAfterEdit() || ImGui::IsKeyPressed(ImGuiKey_Escape)) editID.clear(); + } + else + { + if (ImGui::Selectable(label.c_str(), isSelected, flags)) isActivated = true; + + if ((ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_F2) && isSelected) || + (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))) + { + editID = id; + isJustEdit = true; + } + } + + return isActivated; + } + + void set_item_tooltip_shortcut(const char* tooltip, const std::string& shortcut) + { + ImGui::SetItemTooltip("%s\n(Shortcut: %s)", tooltip, shortcut.c_str()); + } + + void external_storage_set(ImGuiSelectionExternalStorage* self, int id, bool isSelected) + { + auto* set = (std::set*)self->UserData; + if (isSelected) + set->insert(id); + else + set->erase(id); + }; + + std::string chord_to_string(ImGuiKeyChord chord) + { + std::string result; + + if (chord & ImGuiMod_Ctrl) result += "Ctrl+"; + if (chord & ImGuiMod_Shift) result += "Shift+"; + if (chord & ImGuiMod_Alt) result += "Alt+"; + if (chord & ImGuiMod_Super) result += "Super+"; + + if (auto key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); key != ImGuiKey_None) + { + if (const char* name = ImGui::GetKeyName(key); name && *name) + result += name; + else + result += "Unknown"; + } + + if (!result.empty() && result.back() == '+') result.pop_back(); + + return result; + } + + ImGuiKeyChord string_to_chord(const std::string& string) + { + ImGuiKeyChord chord = 0; + ImGuiKey baseKey = ImGuiKey_None; + + std::stringstream ss(string); + std::string token; + while (std::getline(ss, token, '+')) + { + token.erase(0, token.find_first_not_of(" \t\r\n")); + token.erase(token.find_last_not_of(" \t\r\n") + 1); + + if (token.empty()) continue; + + if (auto it = MOD_MAP.find(token); it != MOD_MAP.end()) + chord |= it->second; + else if (baseKey == ImGuiKey_None) + if (auto it2 = KEY_MAP.find(token); it2 != KEY_MAP.end()) baseKey = it2->second; + } + + if (baseKey != ImGuiKey_None) chord |= baseKey; + + return chord; + } + + float row_widget_width_get(int count, float width) + { + return (width - (ImGui::GetStyle().ItemSpacing.x * (float)(count - 1))) / (float)count; + } + + ImVec2 widget_size_with_row_get(int count, float width) { return ImVec2(row_widget_width_get(count, width), 0); } + + float footer_height_get(int itemCount) + { + return ImGui::GetTextLineHeightWithSpacing() * itemCount + ImGui::GetStyle().WindowPadding.y + + ImGui::GetStyle().ItemSpacing.y * (itemCount); + } + + ImVec2 footer_size_get(int itemCount) + { + return ImVec2(ImGui::GetContentRegionAvail().x, footer_height_get(itemCount)); + } + + ImVec2 size_without_footer_get(int rowCount) + { + return ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - footer_height_get(rowCount)); + } + + ImVec2 child_size_get(int rowCount) + { + return ImVec2(ImGui::GetContentRegionAvail().x, + (ImGui::GetFrameHeightWithSpacing() * rowCount) + (ImGui::GetStyle().WindowPadding.y * 2.0f)); + } + + ImVec2 icon_size_get() + { + return ImVec2(ImGui::GetTextLineHeightWithSpacing(), ImGui::GetTextLineHeightWithSpacing()); + } + + bool chord_held(ImGuiKeyChord chord) + { + auto& io = ImGui::GetIO(); + + for (constexpr ImGuiKey mods[] = {ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiMod_Alt, ImGuiMod_Super}; ImGuiKey mod : mods) + { + bool required = (chord & mod) != 0; + if (bool held = io.KeyMods & mod; required && !held) return false; + } + + auto main_key = (ImGuiKey)(chord & ~ImGuiMod_Mask_); + if (main_key == ImGuiKey_None) return false; + + return ImGui::IsKeyDown(main_key); + } + + bool chord_repeating(ImGuiKeyChord chord, float delay, float rate) + { + struct State + { + float timeHeld = 0.f; + float nextRepeat = 0.f; + }; + static std::unordered_map stateMap; + + auto& io = ImGui::GetIO(); + auto& state = stateMap[chord]; + + if (chord_held(chord)) + { + state.timeHeld += io.DeltaTime; + + if (state.timeHeld <= io.DeltaTime) + { + state.nextRepeat = delay; + return true; + } + + if (state.timeHeld >= state.nextRepeat) + { + state.nextRepeat += rate; + return true; + } + } + else + { + state.timeHeld = 0.f; + state.nextRepeat = 0.f; + } + + return false; + } + + bool shortcut(std::string string, shortcut::Type type) + { + if (ImGui::GetTopMostPopupModal() != nullptr) return false; + int flags = type == shortcut::GLOBAL || type == shortcut::GLOBAL_SET ? ImGuiInputFlags_RouteGlobal + : ImGuiInputFlags_RouteFocused; + if (type == shortcut::GLOBAL_SET || type == shortcut::FOCUSED_SET) + { + ImGui::SetNextItemShortcut(string_to_chord(string), flags); + return false; + } + + return ImGui::Shortcut(string_to_chord(string), flags); + } + + MultiSelectStorage::MultiSelectStorage() { internal.AdapterSetItemSelected = external_storage_set; } + + void MultiSelectStorage::start(size_t size, ImGuiMultiSelectFlags flags) + { + internal.UserData = this; + + auto io = ImGui::BeginMultiSelect(flags, this->size(), size); + internal.ApplyRequests(io); + } + + void MultiSelectStorage::finish() + { + auto io = ImGui::EndMultiSelect(); + internal.ApplyRequests(io); + } + + PopupHelper::PopupHelper(const char* label, PopupType type, PopupPosition position) + { + this->label = label; + this->type = type; + this->position = position; + } + + void PopupHelper::open() + { + isOpen = true; + isTriggered = true; + isJustOpened = true; + } + + bool PopupHelper::is_open() { return isOpen; } + + void PopupHelper::trigger() + { + if (isTriggered) ImGui::OpenPopup(label); + isTriggered = false; + + auto viewport = ImGui::GetMainViewport(); + + if (position == POPUP_CENTER) + ImGui::SetNextWindowPos(viewport->GetCenter(), ImGuiCond_None, to_imvec2(vec2(0.5f))); + else + ImGui::SetNextWindowPos(ImGui::GetItemRectMin(), ImGuiCond_None); + + if (POPUP_IS_HEIGHT_SET[type]) + ImGui::SetNextWindowSize(to_imvec2(to_vec2(viewport->Size) * POPUP_MULTIPLIERS[type])); + else + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x * POPUP_MULTIPLIERS[type], 0)); + } + + void PopupHelper::end() { isJustOpened = false; } + + void PopupHelper::close() { isOpen = false; } +} diff --git a/src/imgui/imgui_.h b/src/imgui/imgui_.h new file mode 100644 index 0000000..cef732f --- /dev/null +++ b/src/imgui/imgui_.h @@ -0,0 +1,216 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "types.h" + +namespace anm2ed::imgui +{ + constexpr auto DRAG_SPEED = 1.0f; + constexpr auto STEP = 1.0f; + constexpr auto STEP_FAST = 5.0f; + +#define POPUP_LIST \ + X(POPUP_SMALL, 0.25f, true) \ + X(POPUP_NORMAL, 0.5f, true) \ + X(POPUP_TO_CONTENT, 0.0f, true) \ + X(POPUP_SMALL_NO_HEIGHT, 0.25f, false) \ + X(POPUP_NORMAL_NO_HEIGHT, 0.5f, false) + + enum PopupType + { +#define X(name, multiplier, isHeightSet) name, + POPUP_LIST +#undef X + }; + + enum PopupPosition + { + POPUP_CENTER, + POPUP_BY_ITEM + }; + + constexpr float POPUP_MULTIPLIERS[] = { +#define X(name, multiplier, isHeightSet) multiplier, + POPUP_LIST +#undef X + }; + + constexpr bool POPUP_IS_HEIGHT_SET[] = { +#define X(name, multiplier, isHeightSet) isHeightSet, + POPUP_LIST +#undef X + }; + + const std::unordered_map KEY_MAP = { + {"A", ImGuiKey_A}, + {"B", ImGuiKey_B}, + {"C", ImGuiKey_C}, + {"D", ImGuiKey_D}, + {"E", ImGuiKey_E}, + {"F", ImGuiKey_F}, + {"G", ImGuiKey_G}, + {"H", ImGuiKey_H}, + {"I", ImGuiKey_I}, + {"J", ImGuiKey_J}, + {"K", ImGuiKey_K}, + {"L", ImGuiKey_L}, + {"M", ImGuiKey_M}, + {"N", ImGuiKey_N}, + {"O", ImGuiKey_O}, + {"P", ImGuiKey_P}, + {"Q", ImGuiKey_Q}, + {"R", ImGuiKey_R}, + {"S", ImGuiKey_S}, + {"T", ImGuiKey_T}, + {"U", ImGuiKey_U}, + {"V", ImGuiKey_V}, + {"W", ImGuiKey_W}, + {"X", ImGuiKey_X}, + {"Y", ImGuiKey_Y}, + {"Z", ImGuiKey_Z}, + + {"0", ImGuiKey_0}, + {"1", ImGuiKey_1}, + {"2", ImGuiKey_2}, + {"3", ImGuiKey_3}, + {"4", ImGuiKey_4}, + {"5", ImGuiKey_5}, + {"6", ImGuiKey_6}, + {"7", ImGuiKey_7}, + {"8", ImGuiKey_8}, + {"9", ImGuiKey_9}, + + {"Num0", ImGuiKey_Keypad0}, + {"Num1", ImGuiKey_Keypad1}, + {"Num2", ImGuiKey_Keypad2}, + {"Num3", ImGuiKey_Keypad3}, + {"Num4", ImGuiKey_Keypad4}, + {"Num5", ImGuiKey_Keypad5}, + {"Num6", ImGuiKey_Keypad6}, + {"Num7", ImGuiKey_Keypad7}, + {"Num8", ImGuiKey_Keypad8}, + {"Num9", ImGuiKey_Keypad9}, + {"NumAdd", ImGuiKey_KeypadAdd}, + {"NumSubtract", ImGuiKey_KeypadSubtract}, + {"NumMultiply", ImGuiKey_KeypadMultiply}, + {"NumDivide", ImGuiKey_KeypadDivide}, + {"NumEnter", ImGuiKey_KeypadEnter}, + {"NumDecimal", ImGuiKey_KeypadDecimal}, + + {"F1", ImGuiKey_F1}, + {"F2", ImGuiKey_F2}, + {"F3", ImGuiKey_F3}, + {"F4", ImGuiKey_F4}, + {"F5", ImGuiKey_F5}, + {"F6", ImGuiKey_F6}, + {"F7", ImGuiKey_F7}, + {"F8", ImGuiKey_F8}, + {"F9", ImGuiKey_F9}, + {"F10", ImGuiKey_F10}, + {"F11", ImGuiKey_F11}, + {"F12", ImGuiKey_F12}, + + {"Up", ImGuiKey_UpArrow}, + {"Down", ImGuiKey_DownArrow}, + {"Left", ImGuiKey_LeftArrow}, + {"Right", ImGuiKey_RightArrow}, + + {"Space", ImGuiKey_Space}, + {"Enter", ImGuiKey_Enter}, + {"Escape", ImGuiKey_Escape}, + {"Tab", ImGuiKey_Tab}, + {"Backspace", ImGuiKey_Backspace}, + {"Delete", ImGuiKey_Delete}, + {"Insert", ImGuiKey_Insert}, + {"Home", ImGuiKey_Home}, + {"End", ImGuiKey_End}, + {"PageUp", ImGuiKey_PageUp}, + {"PageDown", ImGuiKey_PageDown}, + + {"Minus", ImGuiKey_Minus}, + {"Equal", ImGuiKey_Equal}, + {"LeftBracket", ImGuiKey_LeftBracket}, + {"RightBracket", ImGuiKey_RightBracket}, + {"Semicolon", ImGuiKey_Semicolon}, + {"Apostrophe", ImGuiKey_Apostrophe}, + {"Comma", ImGuiKey_Comma}, + {"Period", ImGuiKey_Period}, + {"Slash", ImGuiKey_Slash}, + {"Backslash", ImGuiKey_Backslash}, + {"GraveAccent", ImGuiKey_GraveAccent}, + }; + + const std::unordered_map MOD_MAP = { + {"Ctrl", ImGuiMod_Ctrl}, + {"Shift", ImGuiMod_Shift}, + {"Alt", ImGuiMod_Alt}, + {"Super", ImGuiMod_Super}, + }; + + std::string chord_to_string(ImGuiKeyChord); + ImGuiKeyChord string_to_chord(const std::string&); + float row_widget_width_get(int, float = ImGui::GetContentRegionAvail().x); + ImVec2 widget_size_with_row_get(int, float = ImGui::GetContentRegionAvail().x); + float footer_height_get(int = 1); + ImVec2 footer_size_get(int = 1); + ImVec2 size_without_footer_get(int = 1); + ImVec2 child_size_get(int = 1); + int input_text_callback(ImGuiInputTextCallbackData*); + bool input_text_string(const char*, std::string*, ImGuiInputTextFlags = 0); + bool input_int_range(const char*, int&, int, int, int = STEP, int = STEP_FAST, ImGuiInputTextFlags = 0); + bool input_int2_range(const char*, glm::ivec2&, glm::ivec2, glm::ivec2, ImGuiInputTextFlags = 0); + bool input_float_range(const char*, float&, float, float, float = STEP, float = STEP_FAST, const char* = "%.3f", + ImGuiInputTextFlags = 0); + bool combo_negative_one_indexed(const std::string&, int*, std::vector&); + bool selectable_input_text(const std::string&, const std::string&, std::string&, bool = false, + ImGuiSelectableFlags = 0, bool* = nullptr); + void set_item_tooltip_shortcut(const char*, const std::string& = {}); + void external_storage_set(ImGuiSelectionExternalStorage*, int, bool); + ImVec2 icon_size_get(); + bool chord_held(ImGuiKeyChord); + bool chord_repeating(ImGuiKeyChord, float = ImGui::GetIO().KeyRepeatDelay, float = ImGui::GetIO().KeyRepeatRate); + bool shortcut(std::string, types::shortcut::Type = types::shortcut::FOCUSED_SET); + + class MultiSelectStorage : public std::set + { + public: + ImGuiSelectionExternalStorage internal{}; + using std::set::set; + using std::set::operator=; + using std::set::begin; + using std::set::rbegin; + using std::set::end; + using std::set::size; + using std::set::insert; + using std::set::erase; + + MultiSelectStorage(); + void start(size_t, ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_BoxSelect2d | + ImGuiMultiSelectFlags_ClearOnEscape | + ImGuiMultiSelectFlags_ScopeWindow); + void finish(); + }; + + class PopupHelper + { + public: + const char* label{}; + PopupType type{}; + PopupPosition position{}; + bool isOpen{}; + bool isTriggered{}; + bool isJustOpened{}; + + PopupHelper(const char*, PopupType = POPUP_NORMAL, PopupPosition = POPUP_CENTER); + bool is_open(); + void open(); + void trigger(); + void end(); + void close(); + }; +} diff --git a/src/imgui/taskbar.cpp b/src/imgui/taskbar.cpp new file mode 100644 index 0000000..7d624d4 --- /dev/null +++ b/src/imgui/taskbar.cpp @@ -0,0 +1,870 @@ +#include "taskbar.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "math_.h" +#include "render.h" +#include "shader.h" +#include "toast.h" +#include "types.h" + +#include "icon.h" + +using namespace anm2ed::resource; +using namespace anm2ed::types; +using namespace anm2ed::canvas; +using namespace anm2ed::util; +using namespace glm; + +namespace anm2ed::imgui +{ +#ifdef __unix__ + + namespace + { + constexpr std::array ICON_SIZES{16, 24, 32, 48, 64, 128, 256}; + + bool ensure_parent_directory_exists(const std::filesystem::path& path) + { + std::error_code ec; + std::filesystem::create_directories(path.parent_path(), ec); + if (ec) + { + toasts.warning(std::format("Could not create directory for {} ({})", path.string(), ec.message())); + return false; + } + return true; + } + + bool write_binary_blob(const std::filesystem::path& path, const std::uint8_t* data, size_t size) + { + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ios::binary | std::ios::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not open {} for writing", path.string())); + return false; + } + + file.write(reinterpret_cast(data), static_cast(size)); + return true; + } + + bool run_command_checked(const std::string& command, const std::string& description) + { + auto result = std::system(command.c_str()); + if (result != 0) + { + toasts.warning(std::format("{} failed (exit code {})", description, result)); + return false; + } + return true; + } + + bool install_icon_set(const std::string& context, const std::string& iconName, const std::filesystem::path& path) + { + bool success = true; + for (auto size : ICON_SIZES) + { + auto command = std::format("xdg-icon-resource install --noupdate --novendor --context {} --size {} \"{}\" {}", + context, size, path.string(), iconName); + success &= run_command_checked(command, std::format("Install {} icon ({}px)", iconName, size)); + } + return success; + } + + bool uninstall_icon_set(const std::string& context, const std::string& iconName) + { + bool success = true; + for (auto size : ICON_SIZES) + { + auto command = + std::format("xdg-icon-resource uninstall --noupdate --context {} --size {} {}", context, size, iconName); + success &= run_command_checked(command, std::format("Remove {} icon ({}px)", iconName, size)); + } + return success; + } + + bool remove_file_if_exists(const std::filesystem::path& path) + { + std::error_code ec; + if (!std::filesystem::exists(path, ec)) return true; + std::filesystem::remove(path, ec); + if (ec) + { + toasts.warning(std::format("Could not remove {} ({})", path.string(), ec.message())); + return false; + } + return true; + } + } + + constexpr auto MIME_TYPE = R"( + + + Anm2 Animation + + +)"; + + constexpr auto DESKTOP_ENTRY_FORMAT = R"([Desktop Entry] +Type=Application +Name=Anm2Ed +Icon=anm2ed +Comment=Animation editor for .anm2 files +Exec={} +Terminal=false +Categories=Graphics;Development; +MimeType=application/x-anm2+xml; +)"; + +#endif + + Taskbar::Taskbar() : generate(vec2()) {} + + void Taskbar::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, bool& isQuitting) + { + auto document = manager.get(); + auto reference = document ? &document->reference : nullptr; + auto animation = document ? document->animation_get() : nullptr; + auto item = document ? document->item_get() : nullptr; + + if (ImGui::BeginMainMenuBar()) + { + height = ImGui::GetWindowSize().y; + + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("New", settings.shortcutNew.c_str())) dialog.file_save(dialog::ANM2_NEW); + if (ImGui::MenuItem("Open", settings.shortcutOpen.c_str())) dialog.file_open(dialog::ANM2_NEW); + + if (ImGui::BeginMenu("Open Recent", !manager.recentFiles.empty())) + { + for (auto [i, file] : std::views::enumerate(manager.recentFiles)) + { + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + + ImGui::PushID(i); + if (ImGui::MenuItem(label.c_str())) manager.open(file); + ImGui::PopID(); + } + + if (!manager.recentFiles.empty()) + if (ImGui::MenuItem("Clear List")) manager.recent_files_clear(); + + ImGui::EndMenu(); + } + + if (ImGui::MenuItem("Save", settings.shortcutSave.c_str(), false, document)) manager.save(); + if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str(), false, document)) + dialog.file_save(dialog::ANM2_SAVE); + if (ImGui::MenuItem("Explore XML Location", nullptr, false, document)) + dialog.file_explorer_open(document->directory_get()); + + ImGui::Separator(); + if (ImGui::MenuItem("Exit", settings.shortcutExit.c_str())) isQuitting = true; + ImGui::EndMenu(); + } + if (dialog.is_selected(dialog::ANM2_NEW)) + { + manager.new_(dialog.path); + dialog.reset(); + } + + if (dialog.is_selected(dialog::ANM2_OPEN)) + { + manager.open(dialog.path); + dialog.reset(); + } + + if (dialog.is_selected(dialog::ANM2_SAVE)) + { + manager.save(dialog.path); + dialog.reset(); + } + + if (ImGui::BeginMenu("Wizard")) + { + ImGui::BeginDisabled(!item || document->reference.itemType != anm2::LAYER); + if (ImGui::MenuItem("Generate Animation From Grid")) generatePopup.open(); + if (ImGui::MenuItem("Change All Frame Properties")) changePopup.open(); + ImGui::EndDisabled(); + ImGui::Separator(); + if (ImGui::MenuItem("Render Animation", nullptr, false, animation)) renderPopup.open(); + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Playback")) + { + ImGui::MenuItem("Always Loop", nullptr, &settings.playbackIsLoop); + ImGui::SetItemTooltip("%s", "Animations will always loop during playback, even if looping isn't set."); + + ImGui::MenuItem("Clamp Playhead", nullptr, &settings.playbackIsClampPlayhead); + ImGui::SetItemTooltip("%s", "The playhead will always clamp to the animation's length."); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Window")) + { + for (auto [i, member] : std::views::enumerate(WINDOW_MEMBERS)) + ImGui::MenuItem(WINDOW_STRINGS[i], nullptr, &(settings.*member)); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Settings")) + { + if (ImGui::MenuItem("Configure")) + { + editSettings = settings; + configurePopup.open(); + } + + ImGui::Separator(); + + if (ImGui::MenuItem("Associate .anm2 Files with Editor", nullptr, false, + !isAnm2Association || !isAbleToAssociateAnm2)) + { +#ifdef _WIN32 + +#elif __unix__ + auto cache_icons = []() + { + auto programIconPath = std::filesystem::path(filesystem::path_icon_get()); + auto fileIconPath = std::filesystem::path(filesystem::path_icon_file_get()); + auto iconBytes = std::size(resource::icon::PROGRAM); + + bool isSuccess = write_binary_blob(programIconPath, resource::icon::PROGRAM, iconBytes) && + write_binary_blob(fileIconPath, resource::icon::PROGRAM, iconBytes); + + if (isSuccess) + { + isSuccess = install_icon_set("apps", "anm2ed", programIconPath) && + install_icon_set("mimetypes", "application-x-anm2+xml", fileIconPath) && + run_command_checked("xdg-icon-resource forceupdate --theme hicolor", "Refresh icon cache"); + } + + remove_file_if_exists(programIconPath); + remove_file_if_exists(fileIconPath); + + if (isSuccess) toasts.info("Cached program and file icons."); + return isSuccess; + }; + + auto register_mime = []() + { + auto path = std::filesystem::path(filesystem::path_mime_get()); + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ofstream::out | std::ofstream::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not write .anm2 MIME type: {}", path.string())); + return false; + } + + file << MIME_TYPE; + file.close(); + toasts.info(std::format("Wrote .anm2 MIME type to: {}", path.string())); + + auto mimeRoot = path.parent_path().parent_path(); + auto command = std::format("update-mime-database \"{}\"", mimeRoot.string()); + return run_command_checked(command, "Update MIME database"); + }; + + auto register_desktop_entry = []() + { + auto path = std::filesystem::path(filesystem::path_application_get()); + if (!ensure_parent_directory_exists(path)) return false; + + std::ofstream file(path, std::ofstream::out | std::ofstream::trunc); + if (!file.is_open()) + { + toasts.warning(std::format("Could not write desktop entry: {}", path.string())); + return false; + } + + auto desktopEntry = std::format(DESKTOP_ENTRY_FORMAT, filesystem::path_executable_get()); + file << desktopEntry; + file.close(); + toasts.info(std::format("Wrote desktop entry to: {}", path.string())); + + auto desktopDir = path.parent_path(); + auto desktopUpdate = + std::format("update-desktop-database \"{}\"", desktopDir.empty() ? "." : desktopDir.string()); + auto desktopFileName = path.filename().string(); + auto setDefault = std::format("xdg-mime default {} application/x-anm2+xml", + desktopFileName.empty() ? path.string() : desktopFileName); + + auto databaseUpdated = run_command_checked(desktopUpdate, "Update desktop database"); + auto defaultRegistered = run_command_checked(setDefault, "Set default handler for .anm2"); + return databaseUpdated && defaultRegistered; + }; + + auto iconsCached = cache_icons(); + auto mimeRegistered = register_mime(); + auto desktopRegistered = register_desktop_entry(); + + isAnm2Association = iconsCached && mimeRegistered && desktopRegistered; + if (isAnm2Association) + toasts.info("Associated .anm2 files with the editor."); + else + toasts.warning("Association incomplete. Please review the warnings above."); +#endif + } + ImGui::SetItemTooltip( + "Associate .anm2 files with the application (i.e., clicking on them in a file explorer will " + "open the application)."); + + if (ImGui::MenuItem("Remove .anm2 File Association", nullptr, false, + isAnm2Association || !isAbleToAssociateAnm2)) + { +#ifdef _WIN32 + +#elif __unix__ + { + auto iconsRemoved = + uninstall_icon_set("apps", "anm2ed") && uninstall_icon_set("mimetypes", "application-x-anm2+xml") && + run_command_checked("xdg-icon-resource forceupdate --theme hicolor", "Refresh icon cache"); + if (iconsRemoved) + toasts.info("Removed cached icons."); + else + toasts.warning("Could not remove all cached icons."); + } + + { + auto path = std::filesystem::path(filesystem::path_mime_get()); + auto removed = remove_file_if_exists(path); + if (removed) toasts.info(std::format("Removed .anm2 MIME type: {}", path.string())); + + auto mimeRoot = path.parent_path().parent_path(); + run_command_checked(std::format("update-mime-database \"{}\"", mimeRoot.string()), "Update MIME database"); + } + + { + auto path = std::filesystem::path(filesystem::path_application_get()); + if (remove_file_if_exists(path)) toasts.info(std::format("Removed desktop entry: {}", path.string())); + + auto desktopDir = path.parent_path(); + run_command_checked( + std::format("update-desktop-database \"{}\"", desktopDir.empty() ? "." : desktopDir.string()), + "Update desktop database"); + } +#endif + isAnm2Association = false; + } + ImGui::SetItemTooltip("Unassociate .anm2 files with the application."); + + ImGui::EndMenu(); + } + + if (ImGui::BeginMenu("Help")) + { + if (ImGui::MenuItem("About")) aboutPopup.open(); + ImGui::EndMenu(); + } + + ImGui::EndMainMenuBar(); + } + + generatePopup.trigger(); + + if (ImGui::BeginPopupModal(generatePopup.label, &generatePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& startPosition = settings.generateStartPosition; + auto& size = settings.generateSize; + auto& pivot = settings.generatePivot; + auto& rows = settings.generateRows; + auto& columns = settings.generateColumns; + auto& count = settings.generateCount; + auto& delay = settings.generateDelay; + auto& zoom = settings.generateZoom; + auto& zoomStep = settings.viewZoomStep; + + auto childSize = ImVec2(row_widget_width_get(2), size_without_footer_get().y); + + if (ImGui::BeginChild("##Options Child", childSize, ImGuiChildFlags_Borders)) + { + ImGui::InputInt2("Start Position", value_ptr(startPosition)); + ImGui::InputInt2("Frame Size", value_ptr(size)); + ImGui::InputInt2("Pivot", value_ptr(pivot)); + ImGui::InputInt("Rows", &rows, STEP, STEP_FAST); + ImGui::InputInt("Columns", &columns, STEP, STEP_FAST); + + input_int_range("Count", count, anm2::FRAME_NUM_MIN, rows * columns); + + ImGui::InputInt("Delay", &delay, STEP, STEP_FAST); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Preview Child", childSize, ImGuiChildFlags_Borders)) + { + auto& backgroundColor = settings.previewBackgroundColor; + auto& time = generateTime; + auto& shaderTexture = resources.shaders[resource::shader::TEXTURE]; + + auto previewSize = ImVec2(ImGui::GetContentRegionAvail().x, size_without_footer_get(2).y); + + generate.size_set(to_vec2(previewSize)); + generate.bind(); + generate.viewport_set(); + generate.clear(backgroundColor); + + if (document && document->reference.itemType == anm2::LAYER) + { + auto& texture = document->anm2.content + .spritesheets[document->anm2.content.layers[document->reference.itemID].spritesheetID] + .texture; + + auto index = std::clamp((int)(time * (count - 1)), 0, (count - 1)); + auto row = index / columns; + auto column = index % columns; + auto crop = startPosition + ivec2(size.x * column, size.y * row); + auto uvMin = (vec2(crop) + vec2(0.5f)) / vec2(texture.size); + auto uvMax = (vec2(crop) + vec2(size) - vec2(0.5f)) / vec2(texture.size); + + mat4 transform = generate.transform_get(zoom) * math::quad_model_get(size, {}, pivot); + + generate.texture_render(shaderTexture, texture.id, transform, vec4(1.0f), {}, + math::uv_vertices_get(uvMin, uvMax).data()); + } + generate.unbind(); + + ImGui::Image(generate.texture, previewSize); + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::SliderFloat("##Time", &time, 0.0f, 1.0f, ""); + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::InputFloat("##Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + zoom = glm::clamp(zoom, ZOOM_MIN, ZOOM_MAX); + } + + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Generate", widgetSize)) + { + auto generate_from_grid = [&]() + { + item->frames_generate_from_grid(startPosition, size, pivot, columns, count, delay); + animation->frameNum = animation->length(); + }; + + DOCUMENT_EDIT_PTR(document, "Generate Animation from Grid", Document::FRAMES, generate_from_grid()); + + generatePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) generatePopup.close(); + + ImGui::EndPopup(); + } + + changePopup.trigger(); + + if (ImGui::BeginPopupModal(changePopup.label, &changePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& isCrop = settings.changeIsCrop; + auto& isSize = settings.changeIsSize; + auto& isPosition = settings.changeIsPosition; + auto& isPivot = settings.changeIsPivot; + auto& isScale = settings.changeIsScale; + auto& isRotation = settings.changeIsRotation; + auto& isDelay = settings.changeIsDelay; + auto& isTint = settings.changeIsTint; + auto& isColorOffset = settings.changeIsColorOffset; + auto& isVisibleSet = settings.changeIsVisibleSet; + auto& isInterpolatedSet = settings.changeIsInterpolatedSet; + auto& crop = settings.changeCrop; + auto& size = settings.changeSize; + auto& position = settings.changePosition; + auto& pivot = settings.changePivot; + auto& scale = settings.changeScale; + auto& rotation = settings.changeRotation; + auto& delay = settings.changeDelay; + auto& tint = settings.changeTint; + auto& colorOffset = settings.changeColorOffset; + auto& isVisible = settings.changeIsVisible; + auto& isInterpolated = settings.changeIsInterpolated; + + auto& isFromSelectedFrame = settings.changeIsFromSelectedFrame; + auto& numberFrames = settings.changeNumberFrames; + + auto propertiesSize = child_size_get(10); + + if (ImGui::BeginChild("##Properties", propertiesSize, ImGuiChildFlags_Borders)) + { +#define PROPERTIES_WIDGET(body) \ + ImGui::Checkbox(checkboxLabel, &isEnabled); \ + ImGui::SameLine(); \ + ImGui::BeginDisabled(!isEnabled); \ + body; \ + ImGui::EndDisabled(); + + auto bool_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, bool& value) + { PROPERTIES_WIDGET(ImGui::Checkbox(valueLabel, &value)); }; + + auto color3_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec3& value) + { PROPERTIES_WIDGET(ImGui::ColorEdit3(valueLabel, value_ptr(value))); }; + + auto color4_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec4& value) + { PROPERTIES_WIDGET(ImGui::ColorEdit4(valueLabel, value_ptr(value))); }; + + auto float2_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, vec2& value) + { PROPERTIES_WIDGET(ImGui::InputFloat2(valueLabel, value_ptr(value), math::vec2_format_get(value))); }; + + auto float_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, float& value) + { PROPERTIES_WIDGET(ImGui::InputFloat(valueLabel, &value, STEP, STEP_FAST, math::float_format_get(value))); }; + + auto int_value = [&](const char* checkboxLabel, const char* valueLabel, bool& isEnabled, int& value) + { PROPERTIES_WIDGET(ImGui::InputInt(valueLabel, &value, STEP, STEP_FAST)); }; + +#undef PROPERTIES_WIDGET + + float2_value("##Is Crop", "Crop", isCrop, crop); + float2_value("##Is Size", "Size", isSize, size); + float2_value("##Is Position", "Position", isPosition, position); + float2_value("##Is Pivot", "Pivot", isPivot, pivot); + float2_value("##Is Scale", "Scale", isScale, scale); + float_value("##Is Rotation", "Rotation", isRotation, rotation); + int_value("##Is Delay", "Delay", isDelay, delay); + color4_value("##Is Tint", "Tint", isTint, tint); + color3_value("##Is Color Offset", "Color Offset", isColorOffset, colorOffset); + bool_value("##Is Visible", "Visible", isVisibleSet, isVisible); + ImGui::SameLine(); + bool_value("##Is Interpolated", "Interpolated", isInterpolatedSet, isInterpolated); + } + ImGui::EndChild(); + + auto settingsSize = child_size_get(2); + + if (ImGui::BeginChild("##Settings", settingsSize, ImGuiChildFlags_Borders)) + { + ImGui::Checkbox("From Selected Frame", &isFromSelectedFrame); + ImGui::SetItemTooltip("The frames after the currently referenced frame will be changed with these values.\nIf" + " off, will use all frames."); + + ImGui::BeginDisabled(!isFromSelectedFrame); + input_int_range("Number of Frames", numberFrames, anm2::FRAME_NUM_MIN, + item->frames.size() - reference->frameIndex); + ImGui::SetItemTooltip("Set the number of frames that will be changed."); + ImGui::EndDisabled(); + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(4); + + auto frame_change = [&](anm2::ChangeType type) + { + anm2::FrameChange frameChange; + if (isCrop) frameChange.crop = std::make_optional(crop); + if (isSize) frameChange.size = std::make_optional(size); + if (isPosition) frameChange.position = std::make_optional(position); + if (isPivot) frameChange.pivot = std::make_optional(pivot); + if (isScale) frameChange.scale = std::make_optional(scale); + if (isRotation) frameChange.rotation = std::make_optional(rotation); + if (isDelay) frameChange.delay = std::make_optional(delay); + if (isTint) frameChange.tint = std::make_optional(tint); + if (isColorOffset) frameChange.colorOffset = std::make_optional(colorOffset); + if (isVisibleSet) frameChange.isVisible = std::make_optional(isVisible); + if (isInterpolatedSet) frameChange.isInterpolated = std::make_optional(isInterpolated); + + DOCUMENT_EDIT_PTR(document, "Change Frame Properties", Document::FRAMES, + item->frames_change(frameChange, type, + isFromSelectedFrame && document->frame_get() ? reference->frameIndex : 0, + isFromSelectedFrame ? numberFrames : -1)); + + changePopup.close(); + }; + + if (ImGui::Button("Add", widgetSize)) frame_change(anm2::ADD); + ImGui::SameLine(); + if (ImGui::Button("Subtract", widgetSize)) frame_change(anm2::SUBTRACT); + ImGui::SameLine(); + if (ImGui::Button("Adjust", widgetSize)) frame_change(anm2::ADJUST); + ImGui::SameLine(); + if (ImGui::Button("Cancel", widgetSize)) changePopup.close(); + + ImGui::EndPopup(); + } + + configurePopup.trigger(); + + if (ImGui::BeginPopupModal(configurePopup.label, &configurePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = size_without_footer_get(2); + + if (ImGui::BeginTabBar("##Configure Tabs")) + { + if (ImGui::BeginTabItem("General")) + { + if (ImGui::BeginChild("##Tab Child", childSize, true)) + { + ImGui::SeparatorText("File"); + + ImGui::Checkbox("Autosaving", &editSettings.fileIsAutosave); + ImGui::SetItemTooltip("Enables autosaving of documents."); + + ImGui::BeginDisabled(!editSettings.fileIsAutosave); + input_int_range("Autosave Time (minutes)", editSettings.fileAutosaveTime, 0, 10); + ImGui::SetItemTooltip("If changed, will autosave documents using this interval."); + ImGui::EndDisabled(); + + ImGui::SeparatorText("Keyboard"); + + input_float_range("Repeat Delay (seconds)", editSettings.keyboardRepeatDelay, 0.05f, 1.0f, 0.05f, 0.05f, + "%.2f"); + ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired."); + + input_float_range("Repeat Rate (seconds)", editSettings.keyboardRepeatRate, 0.005f, 1.0f, 0.005f, 0.005f, + "%.3f"); + ImGui::SetItemTooltip("Set how often, after repeating begins, key inputs will be fired."); + + ImGui::SeparatorText("UI"); + + input_float_range("UI Scale", editSettings.uiScale, 0.5f, 2.0f, 0.25f, 0.25f, "%.2f"); + ImGui::SetItemTooltip("Change the scale of the UI."); + + ImGui::Checkbox("Vsync", &editSettings.isVsync); + ImGui::SetItemTooltip("Toggle vertical sync; synchronizes program update rate with monitor refresh rate."); + + ImGui::SeparatorText("View"); + + input_float_range("Zoom Step", editSettings.viewZoomStep, 10.0f, 250.0f, 10.0f, 10.0f, "%.0f"); + ImGui::SetItemTooltip("When zooming in/out with mouse or shortcut, this value will be used."); + } + ImGui::EndChild(); + + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Shortcuts")) + { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + if (ImGui::BeginChild("##Tab Child", childSize, true)) + { + if (ImGui::BeginTable("Shortcuts", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) + { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("Shortcut"); + ImGui::TableSetupColumn("Value"); + ImGui::TableHeadersRow(); + + for (int i = 0; i < SHORTCUT_COUNT; ++i) + { + bool isSelected = selectedShortcut == i; + + ShortcutMember member = SHORTCUT_MEMBERS[i]; + std::string* settingString = &(editSettings.*member); + std::string chordString = isSelected ? "" : *settingString; + + ImGui::PushID(i); + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::TextUnformatted(SHORTCUT_STRINGS[i]); + ImGui::TableSetColumnIndex(1); + + if (ImGui::Selectable(chordString.c_str(), isSelected)) selectedShortcut = i; + + ImGui::PopID(); + + if (isSelected) + { + ImGuiKeyChord chord{ImGuiKey_None}; + + if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) chord |= ImGuiMod_Ctrl; + if (ImGui::IsKeyDown(ImGuiMod_Shift)) chord |= ImGuiMod_Shift; + if (ImGui::IsKeyDown(ImGuiMod_Alt)) chord |= ImGuiMod_Alt; + if (ImGui::IsKeyDown(ImGuiMod_Super)) chord |= ImGuiMod_Super; + + for (auto& key : KEY_MAP | std::views::values) + { + if (ImGui::IsKeyPressed(key)) + { + chord |= key; + *settingString = chord_to_string(chord); + selectedShortcut = -1; + break; + } + } + } + } + ImGui::EndTable(); + } + ImGui::EndChild(); + + ImGui::PopStyleVar(); + + ImGui::EndTabItem(); + } + } + + ImGui::EndTabBar(); + } + + auto widgetSize = widget_size_with_row_get(3); + + if (ImGui::Button("Save", widgetSize)) + { + settings = editSettings; + configurePopup.close(); + } + ImGui::SetItemTooltip("Use the configured settings."); + + ImGui::SameLine(); + + if (ImGui::Button("Use Default Settings", widgetSize)) editSettings = Settings(); + ImGui::SetItemTooltip("Reset the settings to their defaults."); + + ImGui::SameLine(); + + if (ImGui::Button("Close", widgetSize)) configurePopup.close(); + ImGui::SetItemTooltip("Close without updating settings."); + + ImGui::EndPopup(); + } + + renderPopup.trigger(); + + if (ImGui::BeginPopupModal(renderPopup.label, &renderPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto animation = document ? document->animation_get() : nullptr; + if (!animation) renderPopup.close(); + + auto& playback = document->playback; + auto& ffmpegPath = settings.renderFFmpegPath; + auto& path = settings.renderPath; + auto& format = settings.renderFormat; + auto& scale = settings.renderScale; + auto& isRaw = settings.renderIsRawAnimation; + auto& type = settings.renderType; + auto& start = manager.recordingStart; + auto& end = manager.recordingEnd; + auto& isRange = manager.isRecordingRange; + auto widgetSize = widget_size_with_row_get(2); + auto dialogType = type == render::PNGS ? dialog::PNG_DIRECTORY_SET + : type == render::GIF ? dialog::GIF_PATH_SET + : type == render::WEBM ? dialog::WEBM_PATH_SET + : dialog::NONE; + + auto replace_extension = [&]() + { path = std::filesystem::path(path).replace_extension(render::EXTENSIONS[type]); }; + + auto range_to_length = [&]() + { + start = 0; + end = animation->frameNum; + }; + + if (renderPopup.isJustOpened) + { + replace_extension(); + if (!isRange) range_to_length(); + } + + if (ImGui::ImageButton("##FFmpeg Path Set", resources.icons[icon::FOLDER].id, icon_size_get())) + dialog.file_open(dialog::FFMPEG_PATH_SET); + ImGui::SameLine(); + input_text_string("FFmpeg Path", &ffmpegPath); + ImGui::SetItemTooltip("Set the path where the FFmpeg installation is located.\nFFmpeg is required to render " + "animations.\nhttps://ffmpeg.org"); + dialog.set_string_to_selected_path(ffmpegPath, dialog::FFMPEG_PATH_SET); + + if (ImGui::ImageButton("##Path Set", resources.icons[icon::FOLDER].id, icon_size_get())) + { + if (dialogType == dialog::PNG_DIRECTORY_SET) + dialog.folder_open(dialogType); + else + dialog.file_save(dialogType); + } + ImGui::SameLine(); + input_text_string(type == render::PNGS ? "Directory" : "Path", &path); + ImGui::SetItemTooltip("Set the output path or directory for the animation."); + dialog.set_string_to_selected_path(path, dialogType); + + if (ImGui::Combo("Type", &type, render::STRINGS, render::COUNT)) replace_extension(); + ImGui::SetItemTooltip("Set the type of the output."); + + ImGui::BeginDisabled(type != render::PNGS); + input_text_string("Format", &format); + ImGui::SetItemTooltip( + "For outputted images, each image will use this format.\n{} represents the index of each image."); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(!isRange); + input_int_range("Start", start, 0, animation->frameNum - 1); + ImGui::SetItemTooltip("Set the starting time of the animation."); + input_int_range("End", end, start + 1, animation->frameNum); + ImGui::SetItemTooltip("Set the ending time of the animation."); + ImGui::EndDisabled(); + + ImGui::BeginDisabled(!isRaw); + input_float_range("Scale", scale, 1.0f, 100.0f, STEP, STEP_FAST, "%.1fx"); + ImGui::SetItemTooltip("Set the output scale of the animation."); + ImGui::EndDisabled(); + + if (ImGui::Checkbox("Custom Range", &isRange)) + if (!isRange) range_to_length(); + ImGui::SetItemTooltip("Toggle using a custom range for the animation."); + + ImGui::SameLine(); + + ImGui::Checkbox("Raw", &isRaw); + ImGui::SetItemTooltip("Record only the raw animation; i.e., only its layers, to its bounds."); + + ImGui::SameLine(); + + ImGui::Checkbox("Sound", &settings.timelineIsSound); + ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window.\nThe " + "output animation will use the played sounds."); + + if (ImGui::Button("Render", widgetSize)) + { + manager.isRecordingStart = true; + playback.time = start; + playback.isPlaying = true; + renderPopup.close(); + manager.progressPopup.open(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) renderPopup.close(); + + ImGui::EndPopup(); + } + + renderPopup.end(); + + aboutPopup.trigger(); + + if (ImGui::BeginPopupModal(aboutPopup.label, &aboutPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + if (ImGui::Button("Close")) aboutPopup.close(); + ImGui::EndPopup(); + } + + if (shortcut(settings.shortcutNew, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_NEW); + if (shortcut(settings.shortcutOpen, shortcut::GLOBAL)) dialog.file_open(dialog::ANM2_OPEN); + if (shortcut(settings.shortcutSave, shortcut::GLOBAL)) document->save(); + if (shortcut(settings.shortcutSaveAs, shortcut::GLOBAL)) dialog.file_save(dialog::ANM2_SAVE); + if (shortcut(settings.shortcutExit, shortcut::GLOBAL)) isQuitting = true; + } +} diff --git a/src/imgui/taskbar.h b/src/imgui/taskbar.h new file mode 100644 index 0000000..778683c --- /dev/null +++ b/src/imgui/taskbar.h @@ -0,0 +1,41 @@ +#pragma once + +#include "canvas.h" +#include "dialog.h" +#include "filesystem_.h" +#include "imgui_.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Taskbar + { + Canvas generate; + float generateTime{}; + PopupHelper generatePopup{PopupHelper("Generate Animation from Grid")}; + PopupHelper changePopup{PopupHelper("Change All Frame Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; + PopupHelper renderPopup{PopupHelper("Render Animation", imgui::POPUP_SMALL_NO_HEIGHT)}; + PopupHelper configurePopup{PopupHelper("Configure")}; + PopupHelper aboutPopup{PopupHelper("About")}; + Settings editSettings{}; + int selectedShortcut{-1}; + +#if defined(_WIN32) || defined(__unix__) + bool isAbleToAssociateAnm2 = true; +#else + bool isAbleToAssociateAnm2 = false; +#endif + + bool isAnm2Association = std::filesystem::exists(util::filesystem::path_application_get()); + + bool isQuittingMode{}; + + public: + float height{}; + + Taskbar(); + void update(Manager&, Settings&, Resources&, Dialog&, bool&); + }; +}; diff --git a/src/imgui/toast.cpp b/src/imgui/toast.cpp new file mode 100644 index 0000000..76196d9 --- /dev/null +++ b/src/imgui/toast.cpp @@ -0,0 +1,89 @@ +#include "toast.h" + +#include "log.h" +#include + +#include "types.h" + +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + constexpr auto LIFETIME = 4.0f; + constexpr auto FADE_THRESHOLD = 1.0f; + + Toast::Toast(const std::string& message) + { + this->message = message; + lifetime = LIFETIME; + } + + void Toasts::update() + { + ImGuiIO& io = ImGui::GetIO(); + + auto borderColor = ImGui::GetStyleColorVec4(ImGuiCol_Border); + auto textColor = ImGui::GetStyleColorVec4(ImGuiCol_Text); + + auto position = to_vec2(io.DisplaySize) - to_vec2(ImGui::GetStyle().ItemSpacing); + + for (int i = (int)toasts.size() - 1; i >= 0; --i) + { + Toast& toast = toasts[i]; + + if (toast.lifetime <= 0.0f) + { + toasts.erase(toasts.begin() + i); + i--; + continue; + } + + toast.lifetime -= ImGui::GetIO().DeltaTime; + + auto alpha = toast.lifetime <= FADE_THRESHOLD ? toast.lifetime / FADE_THRESHOLD : 1.0f; + borderColor.w = alpha; + textColor.w = alpha; + + ImGui::SetNextWindowPos(to_imvec2(position), ImGuiCond_None, {1.0f, 1.0f}); + ImGui::SetNextWindowSize(ImVec2(0, ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().WindowPadding.y)); + ImGui::PushStyleColor(ImGuiCol_Text, textColor); + ImGui::PushStyleColor(ImGuiCol_Border, borderColor); + ImGui::SetNextWindowBgAlpha(alpha); + + if (ImGui::Begin(std::format("##Toast #{}", i).c_str(), nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) + { + ImGui::TextUnformatted(toast.message.c_str()); + position.y -= ImGui::GetWindowSize().y + ImGui::GetStyle().ItemSpacing.y; + + if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) toast.lifetime = 0.0f; + } + ImGui::End(); + ImGui::PopStyleColor(2); + } + } + + void Toasts::info(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.info(message); + } + + void Toasts::error(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.error(message); + } + + void Toasts::warning(const std::string& message) + { + toasts.emplace_back(Toast(message)); + logger.warning(message); + } + +} + +anm2ed::imgui::Toasts toasts; diff --git a/src/imgui/toast.h b/src/imgui/toast.h new file mode 100644 index 0000000..ca33d34 --- /dev/null +++ b/src/imgui/toast.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace anm2ed::imgui +{ + class Toast + { + public: + std::string message{}; + float lifetime{}; + + Toast(const std::string&); + }; + + class Toasts + { + public: + std::vector toasts{}; + + void update(); + void info(const std::string&); + void error(const std::string&); + void warning(const std::string&); + }; + +} + +extern anm2ed::imgui::Toasts toasts; diff --git a/src/imgui/window/animation_preview.cpp b/src/imgui/window/animation_preview.cpp new file mode 100644 index 0000000..5960528 --- /dev/null +++ b/src/imgui/window/animation_preview.cpp @@ -0,0 +1,605 @@ +#include "animation_preview.h" + +#include + +#include + +#include "log.h" +#include "math_.h" +#include "toast.h" +#include "tool.h" +#include "types.h" + +using namespace anm2ed::canvas; +using namespace anm2ed::types; +using namespace anm2ed::util; +using namespace anm2ed::resource; +using namespace glm; + +namespace anm2ed::imgui +{ + constexpr auto NULL_COLOR = vec4(0.0f, 0.0f, 1.0f, 0.90f); + constexpr auto TARGET_SIZE = vec2(32, 32); + constexpr auto POINT_SIZE = vec2(4, 4); + constexpr auto NULL_RECT_SIZE = vec2(100); + constexpr auto TRIGGER_TEXT_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); + + AnimationPreview::AnimationPreview() : Canvas(vec2()) + { + } + + void AnimationPreview::tick(Manager& manager, Document& document, Settings& settings) + { + auto& anm2 = document.anm2; + auto& playback = document.playback; + auto& zoom = document.previewZoom; + auto& pan = document.previewPan; + auto& isRootTransform = settings.previewIsRootTransform; + auto& scale = settings.renderScale; + + if (playback.isPlaying) + { + auto& isSound = settings.timelineIsSound; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + + if (!anm2.content.sounds.empty() && isSound) + { + if (auto animation = document.animation_get(); + animation && animation->triggers.isVisible && (!isOnlyShowLayers || manager.isRecording)) + { + if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); + trigger.is_visible(anm2::TRIGGER)) + if (anm2.content.sounds.contains(trigger.soundID)) anm2.content.sounds[trigger.soundID].audio.play(mixer); + } + } + + document.reference.frameTime = playback.time; + } + + if (manager.isRecording) + { + auto pixels = pixels_get(); + renderFrames.push_back(Texture(pixels.data(), size)); + + if (playback.time > manager.recordingEnd || playback.isFinished) + { + auto& ffmpegPath = settings.renderFFmpegPath; + auto& path = settings.renderPath; + auto& type = settings.renderType; + + if (type == render::PNGS) + { + auto& format = settings.renderFormat; + bool isSuccess{true}; + for (auto [i, frame] : std::views::enumerate(renderFrames)) + { + std::filesystem::path outputPath = + std::filesystem::path(path) / std::vformat(format, std::make_format_args(i)); + + if (!frame.write_png(outputPath)) + { + isSuccess = false; + break; + } + logger.info(std::format("Saved frame to: {}", outputPath.string())); + } + + if (isSuccess) + toasts.info(std::format("Exported rendered frames to: {}", path)); + else + toasts.warning(std::format("Could not export frames to: {}", path)); + } + else + { + if (animation_render(ffmpegPath, path, renderFrames, audioStream, (render::Type)type, size, anm2.info.fps)) + toasts.info(std::format("Exported rendered animation to: {}", path)); + else + toasts.warning(std::format("Could not output rendered animation: {}", path)); + } + + renderFrames.clear(); + + pan = savedPan; + zoom = savedZoom; + settings = savedSettings; + isSizeTrySet = true; + + if (settings.timelineIsSound) audioStream.capture_end(mixer); + + playback.isPlaying = false; + playback.isFinished = false; + manager.isRecording = false; + manager.progressPopup.close(); + } + } + if (manager.isRecordingStart) + { + savedSettings = settings; + + if (settings.timelineIsSound) audioStream.capture_begin(mixer); + + if (settings.renderIsRawAnimation) + { + settings.previewBackgroundColor = vec4(); + settings.previewIsGrid = false; + settings.previewIsAxes = false; + settings.timelineIsOnlyShowLayers = true; + + savedZoom = zoom; + savedPan = pan; + + if (auto animation = document.animation_get()) + { + if (auto rect = animation->rect(isRootTransform); rect != vec4(-1.0f)) + { + size_set(vec2(rect.w, rect.z) * scale); + set_to_rect(zoom, pan, rect); + } + } + + isSizeTrySet = false; + + bind(); + clear(settings.previewBackgroundColor); + unbind(); + } + + manager.isRecordingStart = false; + manager.isRecording = true; + } + } + + void AnimationPreview::update(Manager& manager, Settings& settings, Resources& resources) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& playback = document.playback; + auto& reference = document.reference; + auto animation = document.animation_get(); + auto& pan = document.previewPan; + auto& zoom = document.previewZoom; + auto& backgroundColor = settings.previewBackgroundColor; + auto& axesColor = settings.previewAxesColor; + auto& gridColor = settings.previewGridColor; + auto& gridSize = settings.previewGridSize; + auto& gridOffset = settings.previewGridOffset; + auto& zoomStep = settings.viewZoomStep; + auto& isGrid = settings.previewIsGrid; + auto& overlayTransparency = settings.previewOverlayTransparency; + auto& overlayIndex = document.overlayIndex; + auto& isRootTransform = settings.previewIsRootTransform; + auto& isPivots = settings.previewIsPivots; + auto& isAxes = settings.previewIsAxes; + auto& isAltIcons = settings.previewIsAltIcons; + auto& isBorder = settings.previewIsBorder; + auto& tool = settings.tool; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + auto& shaderLine = resources.shaders[shader::LINE]; + auto& shaderAxes = resources.shaders[shader::AXIS]; + auto& shaderGrid = resources.shaders[shader::GRID]; + auto& shaderTexture = resources.shaders[shader::TEXTURE]; + + auto center_view = [&]() { pan = vec2(); }; + + if (ImGui::Begin("Animation Preview", &settings.windowIsAnimationPreview)) + { + auto childSize = ImVec2(row_widget_width_get(4), + (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::Checkbox("Grid", &isGrid); + ImGui::SetItemTooltip("Toggle the visibility of the grid."); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the grid's color."); + + input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX)); + ImGui::SetItemTooltip("Change the size of all cells in the grid."); + + input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX)); + ImGui::SetItemTooltip("Change the offset of the grid."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + ImGui::SetItemTooltip("Change the zoom of the preview."); + + auto widgetSize = widget_size_with_row_get(2); + + shortcut(settings.shortcutCenterView); + if (ImGui::Button("Center View", widgetSize)) pan = vec2(); + set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); + + ImGui::SameLine(); + + shortcut(settings.shortcutFit); + if (ImGui::Button("Fit", widgetSize)) + if (animation) set_to_rect(zoom, pan, animation->rect(isRootTransform)); + set_item_tooltip_shortcut("Set the view to match the extent of the animation.", settings.shortcutFit); + + ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the background color."); + ImGui::SameLine(); + ImGui::Checkbox("Axes", &isAxes); + ImGui::SetItemTooltip("Toggle the axes' visbility."); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(axesColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Set the color of the axes."); + + combo_negative_one_indexed("Overlay", &overlayIndex, document.animation.labels); + ImGui::SetItemTooltip("Set an animation to be drawn over the current animation."); + + ImGui::InputFloat("Alpha", &overlayTransparency, 0, 0, "%.0f"); + ImGui::SetItemTooltip("Set the alpha of the overlayed animation."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Helpers Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + auto helpersChildSize = ImVec2(row_widget_width_get(2), ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Helpers Child 1", helpersChildSize)) + { + ImGui::Checkbox("Root Transform", &isRootTransform); + ImGui::SetItemTooltip("Root frames will transform the rest of the animation."); + ImGui::Checkbox("Pivots", &isPivots); + ImGui::SetItemTooltip("Toggle the visibility of the animation's pivots."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Helpers Child 2", helpersChildSize)) + { + ImGui::Checkbox("Alt Icons", &isAltIcons); + ImGui::SetItemTooltip("Toggle a different appearance of the target icons."); + ImGui::Checkbox("Border", &isBorder); + ImGui::SetItemTooltip("Toggle the visibility of borders around layers."); + } + ImGui::EndChild(); + } + ImGui::EndChild(); + + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + if (isSizeTrySet) size_set(to_vec2(ImGui::GetContentRegionAvail())); + viewport_set(); + bind(); + clear(backgroundColor); + if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); + if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); + + auto render = [&](anm2::Animation* animation, float time, vec3 colorOffset = {}, float alphaOffset = {}, + bool isOnionskin = false) + { + auto transform = transform_get(zoom, pan); + auto root = animation->rootAnimation.frame_generate(time, anm2::ROOT); + + if (isRootTransform) + transform *= math::quad_model_parent_get(root.position, {}, math::percent_to_unit(root.scale), root.rotation); + + if (!isOnlyShowLayers && root.isVisible && animation->rootAnimation.isVisible) + { + auto rootTransform = transform * math::quad_model_get(TARGET_SIZE, root.position, TARGET_SIZE * 0.5f, + math::percent_to_unit(root.scale), root.rotation); + + vec4 color = isOnionskin ? vec4(colorOffset, alphaOffset) : color::GREEN; + + auto icon = isAltIcons ? icon::TARGET_ALT : icon::TARGET; + texture_render(shaderTexture, resources.icons[icon].id, rootTransform, color); + } + + for (auto& id : animation->layerOrder) + { + auto& layerAnimation = animation->layerAnimations[id]; + if (!layerAnimation.isVisible) continue; + + auto& layer = anm2.content.layers.at(id); + + if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.is_visible()) + { + auto spritesheet = anm2.spritesheet_get(layer.spritesheetID); + if (!spritesheet || !spritesheet->is_valid()) continue; + + auto& texture = spritesheet->texture; + + auto layerModel = math::quad_model_get(frame.size, frame.position, frame.pivot, + math::percent_to_unit(frame.scale), frame.rotation); + auto layerTransform = transform * layerModel; + + auto uvMin = frame.crop / vec2(texture.size); + auto uvMax = (frame.crop + frame.size) / vec2(texture.size); + auto vertices = math::uv_vertices_get(uvMin, uvMax); + vec3 frameColorOffset = frame.colorOffset + colorOffset; + vec4 frameTint = frame.tint; + frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); + + texture_render(shaderTexture, texture.id, layerTransform, frameTint, frameColorOffset, vertices.data()); + + auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : color::RED; + + if (isBorder) rect_render(shaderLine, layerTransform, layerModel, color); + + if (isPivots) + { + auto pivotModel = math::quad_model_get(PIVOT_SIZE, frame.position, PIVOT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + auto pivotTransform = transform * pivotModel; + + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, color); + } + } + } + + for (auto& [id, nullAnimation] : animation->nullAnimations) + { + if (!nullAnimation.isVisible || isOnlyShowLayers) continue; + + auto& isShowRect = anm2.content.nulls[id].isShowRect; + + if (auto frame = nullAnimation.frame_generate(time, anm2::NULL_); frame.isVisible) + { + auto icon = isShowRect ? icon::POINT : isAltIcons ? icon::TARGET_ALT : icon::TARGET; + + auto& size = isShowRect ? POINT_SIZE : TARGET_SIZE; + auto color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) + : id == reference.itemID && reference.itemType == anm2::NULL_ ? color::RED + : NULL_COLOR; + + auto nullModel = math::quad_model_get(size, frame.position, size * 0.5f, math::percent_to_unit(frame.scale), + frame.rotation); + auto nullTransform = transform * nullModel; + + texture_render(shaderTexture, resources.icons[icon].id, nullTransform, color); + + if (isShowRect) + { + auto rectModel = math::quad_model_get(NULL_RECT_SIZE, frame.position, NULL_RECT_SIZE * 0.5f, + math::percent_to_unit(frame.scale), frame.rotation); + auto rectTransform = transform * rectModel; + + rect_render(shaderLine, rectTransform, rectModel, color); + } + } + } + }; + + auto onionskin_render = [&](float time, int count, int direction, vec3 color) + { + for (int i = 1; i <= count; i++) + { + float useTime = time + (float)(direction * i); + if (useTime < 0.0f || useTime > animation->frameNum) continue; + + float alphaOffset = (1.0f / (count + 1)) * i; + render(animation, useTime, color, alphaOffset, true); + } + }; + + auto onionskins_render = [&](float time) + { + onionskin_render(time, settings.onionskinBeforeCount, -1, settings.onionskinBeforeColor); + onionskin_render(time, settings.onionskinAfterCount, 1, settings.onionskinAfterColor); + }; + + auto frameTime = reference.frameTime > -1 && !playback.isPlaying ? reference.frameTime : playback.time; + + if (animation) + { + auto& drawOrder = settings.onionskinDrawOrder; + auto& isEnabled = settings.onionskinIsEnabled; + + if (drawOrder == draw_order::BELOW && isEnabled) onionskins_render(frameTime); + + render(animation, frameTime); + + if (auto overlayAnimation = anm2.animation_get({overlayIndex})) + render(overlayAnimation, frameTime, {}, 1.0f - math::uint8_to_float(overlayTransparency)); + + if (drawOrder == draw_order::ABOVE && isEnabled) onionskins_render(frameTime); + } + + unbind(); + + ImGui::Image(texture, to_imvec2(size)); + + isPreviewHovered = ImGui::IsItemHovered(); + + if (animation && animation->triggers.isVisible && !isOnlyShowLayers && !manager.isRecording) + { + if (auto trigger = animation->triggers.frame_generate(frameTime, anm2::TRIGGER); + trigger.isVisible && trigger.eventID > -1) + { + auto clipMin = ImGui::GetItemRectMin(); + auto clipMax = ImGui::GetItemRectMax(); + auto drawList = ImGui::GetWindowDrawList(); + auto textPos = to_imvec2(to_vec2(cursorScreenPos) + to_vec2(ImGui::GetStyle().WindowPadding)); + + drawList->PushClipRect(clipMin, clipMax); + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE); + drawList->AddText(textPos, ImGui::GetColorU32(TRIGGER_TEXT_COLOR), + anm2.content.events.at(trigger.eventID).name.c_str()); + ImGui::PopFont(); + drawList->PopClipRect(); + } + } + + if (isPreviewHovered) + { + auto isMouseClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); + auto isMouseDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); + auto mouseWheel = ImGui::GetIO().MouseWheel; + + auto isLeftJustPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightJustPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpJustPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownJustPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow); + auto isLeftDown = ImGui::IsKeyDown(ImGuiKey_LeftArrow); + auto isRightDown = ImGui::IsKeyDown(ImGuiKey_RightArrow); + auto isUpDown = ImGui::IsKeyDown(ImGuiKey_UpArrow); + auto isDownDown = ImGui::IsKeyDown(ImGuiKey_DownArrow); + auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); + auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); + auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); + auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); + auto isKeyJustPressed = isLeftJustPressed || isRightJustPressed || isUpJustPressed || isDownJustPressed; + auto isKeyDown = isLeftDown || isRightDown || isUpDown || isDownDown; + auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; + + auto isZoomIn = chord_repeating(string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = chord_repeating(string_to_chord(settings.shortcutZoomOut)); + + auto isBegin = isMouseClicked || isKeyJustPressed; + auto isDuring = isMouseDown || isKeyDown; + auto isEnd = isMouseReleased || isKeyReleased; + + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); + + auto frame = document.frame_get(); + auto useTool = tool; + auto step = isMod ? canvas::STEP_FAST : canvas::STEP; + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + + if (isMouseMiddleDown) useTool = tool::PAN; + if (tool == tool::MOVE && isMouseRightDown) useTool = tool::SCALE; + if (tool == tool::SCALE && isMouseRightDown) useTool = tool::MOVE; + + auto& areaType = tool::INFO[useTool].areaType; + auto cursor = areaType == tool::ANIMATION_PREVIEW || areaType == tool::ALL ? tool::INFO[useTool].cursor + : ImGuiMouseCursor_NotAllowed; + ImGui::SetMouseCursor(cursor); + ImGui::SetKeyboardFocusHere(-1); + + switch (useTool) + { + case tool::PAN: + if (isMouseDown || isMouseMiddleDown) pan += mouseDelta; + break; + case tool::MOVE: + if (!frame) break; + if (isBegin) document.snapshot("Frame Position"); + if (isMouseDown) frame->position = mousePos; + if (isLeftPressed) frame->position.x -= step; + if (isRightPressed) frame->position.x += step; + if (isUpPressed) frame->position.y -= step; + if (isDownPressed) frame->position.y += step; + if (isEnd) document.change(Document::FRAMES); + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto positionFormat = math::vec2_format_get(frame->position); + auto positionString = std::format("Position: ({}, {})", positionFormat, positionFormat); + ImGui::Text(positionString.c_str(), frame->position.x, frame->position.y); + ImGui::EndTooltip(); + } + } + break; + case tool::SCALE: + if (!frame) break; + if (isBegin) document.snapshot("Frame Scale"); + if (isMouseDown) frame->scale += mouseDelta; + if (isLeftPressed) frame->scale.x -= step; + if (isRightPressed) frame->scale.x += step; + if (isUpPressed) frame->scale.y -= step; + if (isDownPressed) frame->scale.y += step; + + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto scaleFormat = math::vec2_format_get(frame->scale); + auto scaleString = std::format("Scale: ({}, {})", scaleFormat, scaleFormat); + ImGui::Text(scaleString.c_str(), frame->scale.x, frame->scale.y); + ImGui::EndTooltip(); + } + } + + if (isEnd) document.change(Document::FRAMES); + break; + case tool::ROTATE: + if (!frame) break; + if (isBegin) document.snapshot("Frame Rotation"); + if (isMouseDown) frame->rotation += mouseDelta.y; + if (isLeftPressed || isDownPressed) frame->rotation -= step; + if (isUpPressed || isRightPressed) frame->rotation += step; + + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto rotationFormat = math::float_format_get(frame->rotation); + auto rotationString = std::format("Rotation: {}", rotationFormat); + ImGui::Text(rotationString.c_str(), frame->rotation); + ImGui::EndTooltip(); + } + } + + if (isEnd) document.change(Document::FRAMES); + break; + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) + zoom_set(zoom, pan, mouseWheel != 0 ? vec2(mousePos) : vec2(), + (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + } + } + ImGui::End(); + + manager.progressPopup.trigger(); + + if (ImGui::BeginPopupModal(manager.progressPopup.label, &manager.progressPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + if (!animation) return; + + auto& start = manager.recordingStart; + auto& end = manager.recordingEnd; + auto progress = (playback.time - start) / (end - start); + + ImGui::ProgressBar(progress); + + if (ImGui::Button("Cancel", ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + playback.isPlaying = false; + manager.isRecording = false; + manager.progressPopup.close(); + } + + ImGui::EndPopup(); + } + + if (!document.isAnimationPreviewSet) + { + center_view(); + zoom = settings.previewStartZoom; + document.isAnimationPreviewSet = true; + } + + settings.previewStartZoom = zoom; + } +} diff --git a/src/imgui/window/animation_preview.h b/src/imgui/window/animation_preview.h new file mode 100644 index 0000000..cbcf380 --- /dev/null +++ b/src/imgui/window/animation_preview.h @@ -0,0 +1,28 @@ +#pragma once + +#include "audio_stream.h" +#include "canvas.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class AnimationPreview : public Canvas + { + MIX_Mixer* mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr); + AudioStream audioStream = AudioStream(mixer); + bool isPreviewHovered{}; + bool isSizeTrySet{true}; + Settings savedSettings{}; + float savedZoom{}; + glm::vec2 savedPan{}; + glm::ivec2 mousePos{}; + std::vector renderFrames{}; + + public: + AnimationPreview(); + void tick(Manager&, Document&, Settings&); + void update(Manager&, Settings&, Resources&); + }; +} diff --git a/src/imgui/window/animations.cpp b/src/imgui/window/animations.cpp new file mode 100644 index 0000000..dcac6c1 --- /dev/null +++ b/src/imgui/window/animations.cpp @@ -0,0 +1,395 @@ +#include "animations.h" + +#include + +#include "toast.h" +#include "vector_.h" + +using namespace anm2ed::util; +using namespace anm2ed::resource; +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + void Animations::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& hovered = document.animation.hovered; + auto& selection = document.animation.selection; + auto& mergeSelection = document.merge.selection; + auto& mergeReference = document.merge.reference; + auto& overlayIndex = document.overlayIndex; + + hovered = -1; + + if (ImGui::Begin("Animations", &settings.windowIsAnimations)) + { + auto childSize = size_without_footer_get(); + + if (ImGui::BeginChild("##Animations Child", childSize, ImGuiChildFlags_Borders)) + { + selection.start(anm2.animations.items.size()); + + for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) + { + ImGui::PushID(i); + + auto isDefault = anm2.animations.defaultAnimation == animation.name; + auto isReferenced = reference.animationIndex == i; + + auto font = isDefault && isReferenced ? font::BOLD_ITALICS + : isDefault ? font::BOLD + : isReferenced ? font::ITALICS + : font::REGULAR; + + ImGui::PushFont(resources.fonts[font].get(), font::SIZE); + ImGui::SetNextItemSelectionUserData((int)i); + if (selectable_input_text(animation.name, std::format("###Document #{} Animation #{}", manager.selected, i), + animation.name, selection.contains((int)i))) + reference = {(int)i}; + if (ImGui::IsItemHovered()) hovered = (int)i; + ImGui::PopFont(); + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(animation.name.c_str()); + ImGui::PopFont(); + + if (isDefault) + { + + ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::TextUnformatted("(Default Animation)"); + ImGui::PopFont(); + } + + ImGui::Text("Length: %d", animation.frameNum); + ImGui::Text("Loop: %s", animation.isLoop ? "true" : "false"); + + ImGui::EndTooltip(); + } + + if (ImGui::BeginDragDropSource()) + { + static std::vector dragDropSelection{}; + dragDropSelection.assign(selection.begin(), selection.end()); + ImGui::SetDragDropPayload("Animation Drag Drop", dragDropSelection.data(), + dragDropSelection.size() * sizeof(int)); + for (auto& i : dragDropSelection) + ImGui::Text("%s", anm2.animations.items[(int)i].name.c_str()); + ImGui::EndDragDropSource(); + } + + if (ImGui::BeginDragDropTarget()) + { + if (auto payload = ImGui::AcceptDragDropPayload("Animation Drag Drop")) + { + auto payloadIndices = (int*)(payload->Data); + auto payloadCount = payload->DataSize / sizeof(int); + std::vector indices(payloadIndices, payloadIndices + payloadCount); + std::sort(indices.begin(), indices.end()); + DOCUMENT_EDIT(document, "Move Animation(s)", Document::ANIMATIONS, + selection = vector::move_indices(anm2.animations.items, indices, i)); + } + ImGui::EndDragDropTarget(); + } + + ImGui::PopID(); + } + + selection.finish(); + + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& i : selection) + clipboardText += anm2.animations.items[i].to_string(); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.animations.items[hovered].to_string()); + }; + + auto cut = [&]() + { + copy(); + + auto remove = [&]() + { + if (!selection.empty()) + { + for (auto& i : selection | std::views::reverse) + anm2.animations.items.erase(anm2.animations.items.begin() + i); + selection.clear(); + } + else if (hovered > -1) + { + anm2.animations.items.erase(anm2.animations.items.begin() + hovered); + hovered = -1; + } + }; + + DOCUMENT_EDIT(document, "Cut Animation(s)", Document::ANIMATIONS, remove()); + }; + + auto paste = [&]() + { + auto clipboardText = clipboard.get(); + + auto deserialize = [&]() + { + auto start = selection.empty() ? anm2.animations.items.size() : *selection.rbegin() + 1; + std::set indices{}; + std::string errorString{}; + if (anm2.animations_deserialize(clipboardText, start, indices, &errorString)) + selection = indices; + else + toasts.error(std::format("Failed to deserialize animation(s): {}", errorString)); + }; + + DOCUMENT_EDIT(document, "Paste Animation(s)", Document::ANIMATIONS, deserialize()); + }; + + if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, !selection.empty() || hovered > -1)) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); + if (ImGui::MenuItem("Paste", settings.shortcutPaste.c_str(), false, !clipboard.is_empty())) paste(); + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(5); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) + { + auto add = [&]() + { + anm2::Animation animation; + if (anm2::Animation* referenceAnimation = document.animation_get()) + { + for (auto [id, layerAnimation] : referenceAnimation->layerAnimations) + animation.layerAnimations[id] = anm2::Item(); + animation.layerOrder = referenceAnimation->layerOrder; + for (auto [id, nullAnimation] : referenceAnimation->nullAnimations) + animation.nullAnimations[id] = anm2::Item(); + } + animation.rootAnimation.frames.emplace_back(anm2::Frame()); + + auto index = 0; + if (!anm2.animations.items.empty()) + index = selection.empty() ? (int)anm2.animations.items.size() - 1 : *selection.rbegin() + 1; + + anm2.animations.items.insert(anm2.animations.items.begin() + index, animation); + selection = {index}; + reference = {index}; + }; + + DOCUMENT_EDIT(document, "Add Animation", Document::ANIMATIONS, add()); + } + set_item_tooltip_shortcut("Add a new animation.", settings.shortcutAdd); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + shortcut(settings.shortcutDuplicate); + if (ImGui::Button("Duplicate", widgetSize)) + { + auto duplicate = [&]() + { + auto duplicated = selection; + auto end = std::ranges::max(duplicated); + for (auto& id : duplicated) + { + anm2.animations.items.insert(anm2.animations.items.begin() + end, anm2.animations.items[id]); + selection.insert(++end); + selection.erase(id); + } + }; + + DOCUMENT_EDIT(document, "Duplicate Animation(s)", Document::ANIMATIONS, duplicate()); + } + set_item_tooltip_shortcut("Duplicate the selected animation(s).", settings.shortcutDuplicate); + + ImGui::SameLine(); + + if (shortcut(settings.shortcutMerge, shortcut::FOCUSED) && !selection.empty()) + { + auto merge_quick = [&]() + { + int merged{}; + if (selection.contains(overlayIndex)) overlayIndex = -1; + + if (selection.size() > 1) + merged = anm2.animations_merge(*selection.begin(), selection); + else if (selection.size() == 1 && *selection.begin() != (int)anm2.animations.items.size() - 1) + { + auto start = *selection.begin(); + auto next = *selection.begin() + 1; + std::set animationSet{}; + animationSet.insert(start); + animationSet.insert(next); + + merged = anm2.animations_merge(start, animationSet); + } + else + return; + + selection = {merged}; + reference = {merged}; + }; + + DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge_quick()) + } + + ImGui::BeginDisabled(selection.size() != 1); + { + if (ImGui::Button("Merge", widgetSize)) + { + mergePopup.open(); + mergeSelection.clear(); + mergeReference = *selection.begin(); + } + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Open the merge popup.\nUsing the shortcut will merge the animations with\nthe last " + "configured merge settings.", + settings.shortcutMerge); + + ImGui::SameLine(); + + shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove", widgetSize)) + { + auto remove = [&]() + { + for (auto& i : selection | std::views::reverse) + { + if (i == overlayIndex) overlayIndex = -1; + anm2.animations.items.erase(anm2.animations.items.begin() + i); + } + selection.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Animation(s)", Document::ANIMATIONS, remove()); + } + set_item_tooltip_shortcut("Remove the selected animation(s).", settings.shortcutDuplicate); + + ImGui::SameLine(); + + shortcut(settings.shortcutDefault); + ImGui::BeginDisabled(selection.size() != 1); + if (ImGui::Button("Default", widgetSize)) + { + DOCUMENT_EDIT(document, "Default Animation", Document::ANIMATIONS, + anm2.animations.defaultAnimation = anm2.animations.items[*selection.begin()].name); + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Set the selected animation as the default.", settings.shortcutDefault); + } + ImGui::EndDisabled(); + + mergePopup.trigger(); + + if (ImGui::BeginPopupModal(mergePopup.label, &mergePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto merge_close = [&]() + { + mergeSelection.clear(); + mergePopup.close(); + }; + + auto& type = settings.mergeType; + auto& isDeleteAnimationsAfter = settings.mergeIsDeleteAnimationsAfter; + + auto footerSize = footer_size_get(); + auto optionsSize = child_size_get(2); + auto deleteAfterSize = child_size_get(); + auto animationsSize = + ImVec2(0, ImGui::GetContentRegionAvail().y - + (optionsSize.y + deleteAfterSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 3)); + + if (ImGui::BeginChild("Animations", animationsSize, ImGuiChildFlags_Borders)) + { + mergeSelection.start(anm2.animations.items.size()); + + for (auto [i, animation] : std::views::enumerate(anm2.animations.items)) + { + if (i == mergeReference) continue; + + ImGui::PushID(i); + + ImGui::SetNextItemSelectionUserData(i); + ImGui::Selectable(animation.name.c_str(), mergeSelection.contains(i)); + + ImGui::PopID(); + } + + mergeSelection.finish(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Merge Options", optionsSize, ImGuiChildFlags_Borders)) + { + auto size = ImVec2(optionsSize.x * 0.5f, optionsSize.y - ImGui::GetStyle().WindowPadding.y * 2); + + if (ImGui::BeginChild("Merge Options 1", size)) + { + ImGui::RadioButton("Append Frames", &type, merge::APPEND); + ImGui::RadioButton("Prepend Frames", &type, merge::PREPEND); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Merge Options 2", size)) + { + ImGui::RadioButton("Replace Frames", &type, merge::REPLACE); + ImGui::RadioButton("Ignore Frames", &type, merge::IGNORE); + } + ImGui::EndChild(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Merge Delete After", deleteAfterSize, ImGuiChildFlags_Borders)) + ImGui::Checkbox("Delete Animations After", &isDeleteAnimationsAfter); + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Merge", widgetSize)) + { + auto merge = [&]() + { + if (mergeSelection.contains(overlayIndex)) overlayIndex = -1; + auto merged = + anm2.animations_merge(mergeReference, mergeSelection, (merge::Type)type, isDeleteAnimationsAfter); + + selection = {merged}; + reference = {merged}; + }; + + DOCUMENT_EDIT(document, "Merge Animations", Document::ANIMATIONS, merge()); + merge_close(); + } + ImGui::SameLine(); + if (ImGui::Button("Close", widgetSize)) merge_close(); + + ImGui::EndPopup(); + } + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/imgui/window/animations.h b/src/imgui/window/animations.h new file mode 100644 index 0000000..6257a29 --- /dev/null +++ b/src/imgui/window/animations.h @@ -0,0 +1,17 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Animations + { + PopupHelper mergePopup{PopupHelper("Merge Animations")}; + + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/events.cpp b/src/imgui/window/events.cpp new file mode 100644 index 0000000..e7f5843 --- /dev/null +++ b/src/imgui/window/events.cpp @@ -0,0 +1,134 @@ +#include "events.h" + +#include + +#include "map_.h" +#include "toast.h" + +using namespace anm2ed::util; +using namespace anm2ed::resource; +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + void Events::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& unused = document.event.unused; + auto& hovered = document.event.hovered; + auto& reference = document.event.reference; + auto& selection = document.event.selection; + + hovered = -1; + + if (ImGui::Begin("Events", &settings.windowIsEvents)) + { + auto childSize = size_without_footer_get(); + + if (ImGui::BeginChild("##Events Child", childSize, true)) + { + selection.start(anm2.content.events.size()); + + for (auto& [id, event] : anm2.content.events) + { + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + if (selectable_input_text(event.name, std::format("###Document #{} Event #{}", manager.selected, id), + event.name, selection.contains(id))) + if (ImGui::IsItemHovered()) hovered = id; + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(event.name.c_str()); + ImGui::PopFont(); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + selection.finish(); + + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& id : selection) + clipboardText += anm2.content.events[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.events[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + std::string errorString{}; + document.snapshot("Paste Event(s)"); + if (anm2.events_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::EVENTS); + else + toasts.error(std::format("Failed to deserialize event(s): {}", errorString)); + }; + + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); + + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) + { + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.events); + anm2.content.events[id] = anm2::Event(); + selection = {id}; + reference = {id}; + }; + + DOCUMENT_EDIT(document, "Add Event", Document::EVENTS, add()); + } + set_item_tooltip_shortcut("Add an event.", settings.shortcutAdd); + ImGui::SameLine(); + + shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.events.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused()); + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Remove unused events (i.e., ones not used by any trigger in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + } +} diff --git a/src/imgui/window/events.h b/src/imgui/window/events.h new file mode 100644 index 0000000..7d01fce --- /dev/null +++ b/src/imgui/window/events.h @@ -0,0 +1,15 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Events + { + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/frame_properties.cpp b/src/imgui/window/frame_properties.cpp new file mode 100644 index 0000000..5ffab31 --- /dev/null +++ b/src/imgui/window/frame_properties.cpp @@ -0,0 +1,124 @@ +#include "frame_properties.h" + +#include + +#include "math_.h" +#include "types.h" + +using namespace anm2ed::util::math; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + void FrameProperties::update(Manager& manager, Settings& settings) + { + if (ImGui::Begin("Frame Properties", &settings.windowIsFrameProperties)) + { + auto& document = *manager.get(); + auto& type = document.reference.itemType; + auto frame = document.frame_get(); + auto useFrame = frame ? *frame : anm2::Frame(); + + ImGui::BeginDisabled(!frame); + { + if (type == anm2::TRIGGER) + { + if (combo_negative_one_indexed("Event", frame ? &useFrame.eventID : &dummy_value(), + document.event.labels)) + DOCUMENT_EDIT(document, "Trigger Event", Document::FRAMES, frame->eventID = useFrame.eventID); + ImGui::SetItemTooltip("Change the event this trigger uses."); + + if (combo_negative_one_indexed("Sound", frame ? &useFrame.soundID : &dummy_value(), + document.sound.labels)) + DOCUMENT_EDIT(document, "Trigger Sound", Document::FRAMES, frame->soundID = useFrame.soundID); + ImGui::SetItemTooltip("Change the sound this trigger uses."); + + if (ImGui::InputInt("At Frame", frame ? &useFrame.atFrame : &dummy_value(), imgui::STEP, + imgui::STEP_FAST, !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) + DOCUMENT_EDIT(document, "Trigger At Frame", Document::FRAMES, frame->atFrame = useFrame.atFrame); + ImGui::SetItemTooltip("Change the frame the trigger will be activated at."); + } + else + { + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Crop", frame ? value_ptr(useFrame.crop) : &dummy_value(), + frame ? vec2_format_get(useFrame.crop) : "")) + DOCUMENT_EDIT(document, "Frame Crop", Document::FRAMES, frame->crop = useFrame.crop); + ImGui::SetItemTooltip("Change the crop position the frame uses."); + + if (ImGui::InputFloat2("Size", frame ? value_ptr(useFrame.size) : &dummy_value(), + frame ? vec2_format_get(useFrame.size) : "")) + DOCUMENT_EDIT(document, "Frame Size", Document::FRAMES, frame->size = useFrame.size); + ImGui::SetItemTooltip("Change the size of the crop the frame uses."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Position", frame ? value_ptr(useFrame.position) : &dummy_value(), + frame ? vec2_format_get(useFrame.position) : "")) + DOCUMENT_EDIT(document, "Frame Position", Document::FRAMES, frame->position = useFrame.position); + ImGui::SetItemTooltip("Change the position of the frame."); + + ImGui::BeginDisabled(type == anm2::ROOT || type == anm2::NULL_); + { + if (ImGui::InputFloat2("Pivot", frame ? value_ptr(useFrame.pivot) : &dummy_value(), + frame ? vec2_format_get(useFrame.pivot) : "")) + DOCUMENT_EDIT(document, "Frame Pivot", Document::FRAMES, frame->pivot = useFrame.pivot); + ImGui::SetItemTooltip("Change the pivot of the frame; i.e., where it is centered."); + } + ImGui::EndDisabled(); + + if (ImGui::InputFloat2("Scale", frame ? value_ptr(useFrame.scale) : &dummy_value(), + frame ? vec2_format_get(useFrame.scale) : "")) + DOCUMENT_EDIT(document, "Frame Scale", Document::FRAMES, frame->scale = useFrame.scale); + ImGui::SetItemTooltip("Change the scale of the frame, in percent."); + + if (ImGui::InputFloat("Rotation", frame ? &useFrame.rotation : &dummy_value(), imgui::STEP, + imgui::STEP_FAST, frame ? float_format_get(useFrame.rotation) : "")) + DOCUMENT_EDIT(document, "Frame Rotation", Document::FRAMES, frame->rotation = useFrame.rotation); + ImGui::SetItemTooltip("Change the rotation of the frame."); + + if (ImGui::InputInt("Duration", frame ? &useFrame.delay : &dummy_value(), imgui::STEP, imgui::STEP_FAST, + !frame ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0)) + DOCUMENT_EDIT(document, "Frame Duration", Document::FRAMES, frame->delay = useFrame.delay); + ImGui::SetItemTooltip("Change how long the frame lasts."); + + if (ImGui::ColorEdit4("Tint", frame ? value_ptr(useFrame.tint) : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Tint", Document::FRAMES, frame->tint = useFrame.tint); + ImGui::SetItemTooltip("Change the tint of the frame."); + + if (ImGui::ColorEdit3("Color Offset", frame ? value_ptr(useFrame.colorOffset) : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Color Offset", Document::FRAMES, frame->colorOffset = useFrame.colorOffset); + ImGui::SetItemTooltip("Change the color added onto the frame."); + + if (ImGui::Checkbox("Visible", frame ? &useFrame.isVisible : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Visibility", Document::FRAMES, frame->isVisible = useFrame.isVisible); + ImGui::SetItemTooltip("Toggle the frame's visibility."); + + ImGui::SameLine(); + + if (ImGui::Checkbox("Interpolated", frame ? &useFrame.isInterpolated : &dummy_value())) + DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, + frame->isInterpolated = useFrame.isInterpolated); + ImGui::SetItemTooltip( + "Toggle the frame interpolating; i.e., blending its values into the next frame based on the time."); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + if (ImGui::Button("Flip X", widgetSize)) + DOCUMENT_EDIT(document, "Frame Flip X", Document::FRAMES, frame->scale.x = -frame->scale.x); + ImGui::SetItemTooltip("%s", "Flip the horizontal scale of the frame, to cheat mirroring the frame " + "horizontally.\n(Note: the format does not support mirroring.)"); + ImGui::SameLine(); + if (ImGui::Button("Flip Y", widgetSize)) + DOCUMENT_EDIT(document, "Frame Flip Y", Document::FRAMES, frame->scale.y = -frame->scale.y); + ImGui::SetItemTooltip("%s", "Flip the vertical scale of the frame, to cheat mirroring the frame " + "vertically.\n(Note: the format does not support mirroring.)"); + } + } + ImGui::EndDisabled(); + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/imgui/window/frame_properties.h b/src/imgui/window/frame_properties.h new file mode 100644 index 0000000..d8cfd86 --- /dev/null +++ b/src/imgui/window/frame_properties.h @@ -0,0 +1,13 @@ +#pragma once + +#include "manager.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class FrameProperties + { + public: + void update(Manager&, Settings&); + }; +} diff --git a/src/imgui/window/layers.cpp b/src/imgui/window/layers.cpp new file mode 100644 index 0000000..b09d1e9 --- /dev/null +++ b/src/imgui/window/layers.cpp @@ -0,0 +1,186 @@ +#include "layers.h" + +#include + +#include "map_.h" +#include "toast.h" + +using namespace anm2ed::util; +using namespace anm2ed::resource; +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + void Layers::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.layer.reference; + auto& unused = document.layer.unused; + auto& hovered = document.layer.hovered; + auto& selection = document.layer.selection; + auto& propertiesPopup = manager.layerPropertiesPopup; + + hovered = -1; + + if (ImGui::Begin("Layers", &settings.windowIsLayers)) + { + auto childSize = size_without_footer_get(); + + if (ImGui::BeginChild("##Layers Child", childSize, true)) + { + selection.start(anm2.content.layers.size()); + + for (auto& [id, layer] : anm2.content.layers) + { + auto isSelected = selection.contains(id); + + ImGui::PushID(id); + + ImGui::SetNextItemSelectionUserData(id); + ImGui::Selectable(std::format(anm2::LAYER_FORMAT, id, layer.name, layer.spritesheetID).c_str(), isSelected); + if (ImGui::IsItemHovered()) + { + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.layer_properties_open(id); + } + else + hovered = -1; + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(layer.name.c_str()); + ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::Text("Spritesheet ID: %d", layer.spritesheetID); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + selection.finish(); + + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& id : selection) + clipboardText += anm2.content.layers[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.layers[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + std::string errorString{}; + document.snapshot("Paste Layer(s)"); + if (anm2.layers_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::NULLS); + else + toasts.error(std::format("Failed to deserialize layer(s): {}", errorString)); + }; + + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); + + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) manager.layer_properties_open(); + set_item_tooltip_shortcut("Add a layer.", settings.shortcutAdd); + ImGui::SameLine(); + + shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.layers.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Layers", Document::LAYERS, remove_unused()); + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Remove unused layers (i.e., ones not used in any animation.)", + settings.shortcutRemove); + } + ImGui::End(); + + manager.layer_properties_trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = child_size_get(2); + auto& layer = manager.editLayer; + + if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) + { + if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); + input_text_string("Name", &layer.name); + ImGui::SetItemTooltip("Set the item's name."); + combo_negative_one_indexed("Spritesheet", &layer.spritesheetID, document.spritesheet.labels); + ImGui::SetItemTooltip("Set the layer item's spritesheet."); + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) + { + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.layers); + anm2.content.layers[id] = layer; + selection = {id}; + }; + + auto set = [&]() + { + anm2.content.layers[reference] = layer; + selection = {reference}; + }; + + if (reference == -1) + { + DOCUMENT_EDIT(document, "Add Layer", Document::LAYERS, add()); + } + else + DOCUMENT_EDIT(document, "Set Layer Properties", Document::LAYERS, set()); + + manager.layer_properties_close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) manager.layer_properties_close(); + + manager.layer_properties_end(); + ImGui::EndPopup(); + } + } +} diff --git a/src/imgui/window/layers.h b/src/imgui/window/layers.h new file mode 100644 index 0000000..2431571 --- /dev/null +++ b/src/imgui/window/layers.h @@ -0,0 +1,15 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Layers + { + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/nulls.cpp b/src/imgui/window/nulls.cpp new file mode 100644 index 0000000..db776f0 --- /dev/null +++ b/src/imgui/window/nulls.cpp @@ -0,0 +1,187 @@ +#include "nulls.h" + +#include + +#include "map_.h" +#include "toast.h" + +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace anm2ed::types; + +namespace anm2ed::imgui +{ + void Nulls::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.null.reference; + auto& unused = document.null.unused; + auto& hovered = document.null.hovered; + auto& selection = document.null.selection; + auto& propertiesPopup = manager.nullPropertiesPopup; + + hovered = -1; + + if (ImGui::Begin("Nulls", &settings.windowIsNulls)) + { + auto childSize = size_without_footer_get(); + + if (ImGui::BeginChild("##Nulls Child", childSize, true)) + { + selection.start(anm2.content.nulls.size()); + + for (auto& [id, null] : anm2.content.nulls) + { + auto isSelected = selection.contains(id); + auto isReferenced = reference == id; + + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::Selectable(std::format(anm2::NULL_FORMAT, id, null.name).c_str(), isSelected); + if (ImGui::IsItemHovered()) + { + hovered = id; + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) manager.null_properties_open(id); + } + + if (isReferenced) ImGui::PopFont(); + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(null.name.c_str()); + ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + selection.finish(); + + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& id : selection) + clipboardText += anm2.content.nulls[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.nulls[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + std::string errorString{}; + document.snapshot("Paste Null(s)"); + if (anm2.nulls_deserialize(clipboard.get(), type, &errorString)) + document.change(Document::NULLS); + else + toasts.error(std::format("Failed to deserialize null(s): {}", errorString)); + }; + + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, selection.empty() || hovered > -1)) copy(); + + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) manager.null_properties_open(); + set_item_tooltip_shortcut("Add a null.", settings.shortcutAdd); + ImGui::SameLine(); + + shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.nulls.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Events", Document::EVENTS, remove_unused()); + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Remove unused nulls (i.e., ones not used in any animation.)", settings.shortcutRemove); + } + ImGui::End(); + + manager.null_properties_trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto childSize = child_size_get(2); + auto& null = manager.editNull; + + if (ImGui::BeginChild("Child", childSize, ImGuiChildFlags_Borders)) + { + if (propertiesPopup.isJustOpened) ImGui::SetKeyboardFocusHere(); + input_text_string("Name", &null.name); + ImGui::SetItemTooltip("Set the null's name."); + + ImGui::Checkbox("Rect", &null.isShowRect); + ImGui::SetItemTooltip("The null will have a rectangle show around it."); + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button(reference == -1 ? "Add" : "Confirm", widgetSize)) + { + auto add = [&]() + { + auto id = map::next_id_get(anm2.content.nulls); + anm2.content.nulls[id] = null; + selection = {id}; + }; + + auto set = [&]() + { + anm2.content.nulls[reference] = null; + selection = {reference}; + }; + + if (reference == -1) + { + DOCUMENT_EDIT(document, "Add Null", Document::NULLS, add()); + } + else + DOCUMENT_EDIT(document, "Set Null Properties", Document::NULLS, set()); + + manager.null_properties_close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) manager.null_properties_close(); + + ImGui::EndPopup(); + } + + manager.null_properties_end(); + } +} \ No newline at end of file diff --git a/src/imgui/window/nulls.h b/src/imgui/window/nulls.h new file mode 100644 index 0000000..7ffd1fd --- /dev/null +++ b/src/imgui/window/nulls.h @@ -0,0 +1,15 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Nulls + { + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} \ No newline at end of file diff --git a/src/imgui/window/onionskin.cpp b/src/imgui/window/onionskin.cpp new file mode 100644 index 0000000..793d5b1 --- /dev/null +++ b/src/imgui/window/onionskin.cpp @@ -0,0 +1,55 @@ +#include "onionskin.h" + +#include + +#include "imgui_.h" + +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + constexpr auto FRAMES_MAX = 100; + + void Onionskin::update(Settings& settings) + { + auto& isEnabled = settings.onionskinIsEnabled; + auto& beforeCount = settings.onionskinBeforeCount; + auto& beforeColor = settings.onionskinBeforeColor; + auto& afterCount = settings.onionskinAfterCount; + auto& afterColor = settings.onionskinAfterColor; + auto& drawOrder = settings.onionskinDrawOrder; + + if (ImGui::Begin("Onionskin", &settings.windowIsOnionskin)) + { + auto configure_widgets = [&](const char* separator, int& frames, vec3& color) + { + ImGui::PushID(separator); + ImGui::SeparatorText(separator); + input_int_range("Frames", frames, 0, FRAMES_MAX); + ImGui::SetItemTooltip("Change the amount of frames this onionskin will use."); + ImGui::ColorEdit3("Color", value_ptr(color)); + ImGui::SetItemTooltip("Change the color of the frames this onionskin will use."); + ImGui::PopID(); + }; + + ImGui::Checkbox("Enabled", &isEnabled); + set_item_tooltip_shortcut("Toggle onionskinning.", settings.shortcutOnionskin); + + configure_widgets("Before", beforeCount, beforeColor); + configure_widgets("After", afterCount, afterColor); + + ImGui::Text("Draw Order"); + ImGui::SameLine(); + ImGui::RadioButton("Below", &drawOrder, draw_order::BELOW); + ImGui::SetItemTooltip("The onionskin frames will draw below the original frames."); + ImGui::SameLine(); + ImGui::RadioButton("Above", &drawOrder, draw_order::ABOVE); + ImGui::SetItemTooltip("The onionskin frames will draw above the original frames."); + } + ImGui::End(); + + if (shortcut(settings.shortcutOnionskin, shortcut::GLOBAL)) isEnabled = !isEnabled; + } + +} diff --git a/src/imgui/window/onionskin.h b/src/imgui/window/onionskin.h new file mode 100644 index 0000000..6b23aed --- /dev/null +++ b/src/imgui/window/onionskin.h @@ -0,0 +1,12 @@ +#pragma once + +#include "settings.h" + +namespace anm2ed::imgui +{ + class Onionskin + { + public: + void update(Settings&); + }; +} diff --git a/src/imgui/window/sounds.cpp b/src/imgui/window/sounds.cpp new file mode 100644 index 0000000..35f1cf4 --- /dev/null +++ b/src/imgui/window/sounds.cpp @@ -0,0 +1,148 @@ +#include "sounds.h" + +#include + +#include "toast.h" + +using namespace anm2ed::dialog; +using namespace anm2ed::types; +using namespace anm2ed::resource; + +namespace anm2ed::imgui +{ + void Sounds::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.sound.reference; + auto& unused = document.sound.unused; + auto& hovered = document.null.hovered; + auto& selection = document.sound.selection; + + hovered = -1; + + if (ImGui::Begin("Sounds", &settings.windowIsSounds)) + { + auto childSize = imgui::size_without_footer_get(); + + if (ImGui::BeginChild("##Sounds Child", childSize, true)) + { + selection.start(anm2.content.sounds.size()); + + for (auto& [id, sound] : anm2.content.sounds) + { + auto isSelected = selection.contains(id); + auto isReferenced = reference == id; + + ImGui::PushID(id); + ImGui::SetNextItemSelectionUserData(id); + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + if (ImGui::Selectable(sound.path.c_str(), isSelected)) sound.play(); + if (ImGui::IsItemHovered()) hovered = id; + + if (isReferenced) ImGui::PopFont(); + + if (ImGui::BeginItemTooltip()) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(sound.path.c_str()); + ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::Text("Click to play."); + ImGui::EndTooltip(); + } + ImGui::PopID(); + } + + selection.finish(); + + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& id : selection) + clipboardText += anm2.content.sounds[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.sounds[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + std::string errorString{}; + document.snapshot("Paste Sound(s)"); + if (anm2.sounds_deserialize(clipboard.get(), document.directory_get(), type, &errorString)) + document.change(Document::SOUNDS); + else + toasts.error(std::format("Failed to deserialize sound(s): {}", errorString)); + }; + + if (imgui::shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (imgui::shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, false); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), !selection.empty() && hovered > -1)) copy(); + + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + + ImGui::EndPopup(); + } + } + ImGui::EndChild(); + + auto widgetSize = imgui::widget_size_with_row_get(2); + + imgui::shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) dialog.file_open(dialog::SOUND_OPEN); + imgui::set_item_tooltip_shortcut("Add a sound.", settings.shortcutAdd); + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutRemove); + ImGui::BeginDisabled(unused.empty()); + if (ImGui::Button("Remove Unused", widgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + anm2.content.sounds.erase(id); + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Sounds", Document::SOUNDS, remove_unused()); + }; + ImGui::EndDisabled(); + imgui::set_item_tooltip_shortcut("Remove unused sounds (i.e., ones not used in any trigger.)", + settings.shortcutRemove); + } + ImGui::End(); + + if (dialog.is_selected(dialog::SOUND_OPEN)) + { + auto add = [&]() + { + int id{}; + if (anm2.sound_add(document.directory_get(), dialog.path, id)) + { + selection = {id}; + toasts.info(std::format("Initialized sound #{}: {}", id, dialog.path)); + } + else + toasts.error(std::format("Failed to initialize sound: {}", dialog.path)); + }; + + DOCUMENT_EDIT(document, "Add Sound", Document::SOUNDS, add()); + + dialog.reset(); + } + } +} \ No newline at end of file diff --git a/src/imgui/window/sounds.h b/src/imgui/window/sounds.h new file mode 100644 index 0000000..c39efa6 --- /dev/null +++ b/src/imgui/window/sounds.h @@ -0,0 +1,16 @@ +#pragma once + +#include "clipboard.h" +#include "dialog.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Sounds + { + public: + void update(Manager&, Settings&, Resources&, Dialog&, Clipboard&); + }; +} diff --git a/src/imgui/window/spritesheet_editor.cpp b/src/imgui/window/spritesheet_editor.cpp new file mode 100644 index 0000000..7d91fb5 --- /dev/null +++ b/src/imgui/window/spritesheet_editor.cpp @@ -0,0 +1,355 @@ +#include "spritesheet_editor.h" + +#include +#include + +#include "math_.h" +#include "tool.h" +#include "types.h" + +using namespace anm2ed::canvas; +using namespace anm2ed::types; +using namespace anm2ed::resource; +using namespace anm2ed::util; +using namespace glm; + +namespace anm2ed::imgui +{ + constexpr auto PIVOT_COLOR = color::PINK; + + SpritesheetEditor::SpritesheetEditor() : Canvas(vec2()) + { + } + + void SpritesheetEditor::update(Manager& manager, Settings& settings, Resources& resources) + { + + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& reference = document.reference; + auto& referenceSpritesheet = document.spritesheet.reference; + auto& pan = document.editorPan; + auto& zoom = document.editorZoom; + auto& backgroundColor = settings.editorBackgroundColor; + auto& gridColor = settings.editorGridColor; + auto& gridSize = settings.editorGridSize; + auto& gridOffset = settings.editorGridOffset; + auto& toolColor = settings.toolColor; + auto& isGrid = settings.editorIsGrid; + auto& isGridSnap = settings.editorIsGridSnap; + auto& zoomStep = settings.viewZoomStep; + auto& isBorder = settings.editorIsBorder; + auto spritesheet = document.spritesheet_get(); + auto& tool = settings.tool; + auto& shaderGrid = resources.shaders[shader::GRID]; + auto& shaderTexture = resources.shaders[shader::TEXTURE]; + auto& dashedShader = resources.shaders[shader::DASHED]; + + auto center_view = [&]() { pan = -size * 0.5f; }; + + if (ImGui::Begin("Spritesheet Editor", &settings.windowIsSpritesheetEditor)) + { + auto childSize = ImVec2(imgui::row_widget_width_get(3), + (ImGui::GetTextLineHeightWithSpacing() * 4) + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild("##Grid Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::Checkbox("Grid", &isGrid); + ImGui::SetItemTooltip("Toggle the visibility of the grid."); + ImGui::SameLine(); + ImGui::Checkbox("Snap", &isGridSnap); + ImGui::SetItemTooltip("Cropping will snap points to the grid."); + ImGui::SameLine(); + ImGui::ColorEdit4("Color", value_ptr(gridColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the grid's color."); + + input_int2_range("Size", gridSize, ivec2(GRID_SIZE_MIN), ivec2(GRID_SIZE_MAX)); + ImGui::SetItemTooltip("Change the size of all cells in the grid."); + + input_int2_range("Offset", gridOffset, ivec2(GRID_OFFSET_MIN), ivec2(GRID_OFFSET_MAX)); + ImGui::SetItemTooltip("Change the offset of the grid."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##View Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::InputFloat("Zoom", &zoom, zoomStep, zoomStep, "%.0f%%"); + ImGui::SetItemTooltip("Change the zoom of the editor."); + + auto widgetSize = ImVec2(imgui::row_widget_width_get(2), 0); + + imgui::shortcut(settings.shortcutCenterView); + if (ImGui::Button("Center View", widgetSize)) center_view(); + imgui::set_item_tooltip_shortcut("Centers the view.", settings.shortcutCenterView); + + ImGui::SameLine(); + + imgui::shortcut(settings.shortcutFit); + if (ImGui::Button("Fit", widgetSize)) + if (spritesheet) set_to_rect(zoom, pan, {0, 0, spritesheet->texture.size.x, spritesheet->texture.size.y}); + imgui::set_item_tooltip_shortcut("Set the view to match the extent of the spritesheet.", settings.shortcutFit); + + ImGui::TextUnformatted(std::format(POSITION_FORMAT, (int)mousePos.x, (int)mousePos.y).c_str()); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Background Child", childSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + ImGui::ColorEdit4("Background", value_ptr(backgroundColor), ImGuiColorEditFlags_NoInputs); + ImGui::SetItemTooltip("Change the background color."); + + ImGui::Checkbox("Border", &isBorder); + ImGui::SetItemTooltip("Toggle a border appearing around the spritesheet."); + } + ImGui::EndChild(); + + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + size_set(to_vec2(ImGui::GetContentRegionAvail())); + bind(); + viewport_set(); + clear(backgroundColor); + + auto frame = document.frame_get(); + + if (spritesheet && spritesheet->texture.is_valid()) + { + auto& texture = spritesheet->texture; + auto transform = transform_get(zoom, pan); + + auto spritesheetModel = math::quad_model_get(texture.size); + auto spritesheetTransform = transform * spritesheetModel; + texture_render(shaderTexture, texture.id, spritesheetTransform); + if (isBorder) rect_render(dashedShader, spritesheetTransform, spritesheetModel); + + if (frame && reference.itemID > -1 && + anm2.content.layers.at(reference.itemID).spritesheetID == referenceSpritesheet) + { + auto cropModel = math::quad_model_get(frame->size, frame->crop); + auto cropTransform = transform * cropModel; + rect_render(dashedShader, cropTransform, cropModel, color::RED); + + auto pivotTransform = + transform * math::quad_model_get(canvas::PIVOT_SIZE, frame->crop + frame->pivot, PIVOT_SIZE * 0.5f); + texture_render(shaderTexture, resources.icons[icon::PIVOT].id, pivotTransform, PIVOT_COLOR); + } + } + + if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); + + unbind(); + + ImGui::Image(texture, to_imvec2(size)); + + if (ImGui::IsItemHovered()) + { + auto isMouseLeftClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Left); + auto isMouseLeftReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Left); + auto isMouseLeftDown = ImGui::IsMouseDown(ImGuiMouseButton_Left); + auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle); + auto isMouseRightClicked = ImGui::IsMouseClicked(ImGuiMouseButton_Right); + auto isMouseRightDown = ImGui::IsMouseDown(ImGuiMouseButton_Right); + auto isMouseRightReleased = ImGui::IsMouseReleased(ImGuiMouseButton_Right); + auto mouseDelta = to_ivec2(ImGui::GetIO().MouseDelta); + auto mouseWheel = ImGui::GetIO().MouseWheel; + auto isMouseClicked = isMouseLeftClicked || isMouseRightClicked; + auto isMouseDown = isMouseLeftDown || isMouseRightDown; + auto isMouseReleased = isMouseLeftReleased || isMouseRightReleased; + + auto isLeftJustPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow, false); + auto isRightJustPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow, false); + auto isUpJustPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false); + auto isDownJustPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow, false); + auto isLeftPressed = ImGui::IsKeyPressed(ImGuiKey_LeftArrow); + auto isRightPressed = ImGui::IsKeyPressed(ImGuiKey_RightArrow); + auto isUpPressed = ImGui::IsKeyPressed(ImGuiKey_UpArrow); + auto isDownPressed = ImGui::IsKeyPressed(ImGuiKey_DownArrow); + auto isLeftDown = ImGui::IsKeyDown(ImGuiKey_LeftArrow); + auto isRightDown = ImGui::IsKeyDown(ImGuiKey_RightArrow); + auto isUpDown = ImGui::IsKeyDown(ImGuiKey_UpArrow); + auto isDownDown = ImGui::IsKeyDown(ImGuiKey_DownArrow); + auto isLeftReleased = ImGui::IsKeyReleased(ImGuiKey_LeftArrow); + auto isRightReleased = ImGui::IsKeyReleased(ImGuiKey_RightArrow); + auto isUpReleased = ImGui::IsKeyReleased(ImGuiKey_UpArrow); + auto isDownReleased = ImGui::IsKeyReleased(ImGuiKey_DownArrow); + auto isKeyJustPressed = isLeftJustPressed || isRightJustPressed || isUpJustPressed || isDownJustPressed; + auto isKeyDown = isLeftDown || isRightDown || isUpDown || isDownDown; + auto isKeyReleased = isLeftReleased || isRightReleased || isUpReleased || isDownReleased; + + auto isZoomIn = chord_repeating(string_to_chord(settings.shortcutZoomIn)); + auto isZoomOut = chord_repeating(string_to_chord(settings.shortcutZoomOut)); + + auto isBegin = isMouseClicked || isKeyJustPressed; + auto isDuring = isMouseDown || isKeyDown; + auto isEnd = isMouseReleased || isKeyReleased; + + auto isMod = ImGui::IsKeyDown(ImGuiMod_Shift); + + auto frame = document.frame_get(); + auto useTool = tool; + auto step = isMod ? canvas::STEP_FAST : canvas::STEP; + auto stepX = isGridSnap ? step * gridSize.x : step; + auto stepY = isGridSnap ? step * gridSize.y : step; + previousMousePos = mousePos; + mousePos = position_translate(zoom, pan, to_vec2(ImGui::GetMousePos()) - to_vec2(cursorScreenPos)); + + auto snap_rect = [&](glm::vec2 minPoint, glm::vec2 maxPoint) + { + if (isGridSnap) + { + if (gridSize.x != 0) + { + minPoint.x = std::floor(minPoint.x / gridSize.x) * gridSize.x; + maxPoint.x = std::ceil(maxPoint.x / gridSize.x) * gridSize.x; + } + if (gridSize.y != 0) + { + minPoint.y = std::floor(minPoint.y / gridSize.y) * gridSize.y; + maxPoint.y = std::ceil(maxPoint.y / gridSize.y) * gridSize.y; + } + } + return std::pair{minPoint, maxPoint}; + }; + + if (isMouseMiddleDown) useTool = tool::PAN; + if (tool == tool::MOVE && isMouseRightDown) useTool = tool::CROP; + if (tool == tool::CROP && isMouseRightDown) useTool = tool::MOVE; + if (tool == tool::DRAW && isMouseRightDown) useTool = tool::ERASE; + if (tool == tool::ERASE && isMouseRightDown) useTool = tool::DRAW; + + auto& areaType = tool::INFO[useTool].areaType; + auto cursor = areaType == tool::SPRITESHEET_EDITOR || areaType == tool::ALL ? tool::INFO[useTool].cursor + : ImGuiMouseCursor_NotAllowed; + ImGui::SetMouseCursor(cursor); + ImGui::SetKeyboardFocusHere(-1); + + switch (useTool) + { + case tool::PAN: + if (isMouseDown || isMouseMiddleDown) pan += mouseDelta; + break; + case tool::MOVE: + if (!frame) break; + if (isBegin) document.snapshot("Frame Pivot"); + if (isMouseDown) frame->pivot = ivec2(mousePos - frame->crop); + if (isLeftPressed) frame->pivot.x -= step; + if (isRightPressed) frame->pivot.x += step; + if (isUpPressed) frame->pivot.y -= step; + if (isDownPressed) frame->pivot.y += step; + if (isDuring) + { + if (ImGui::BeginTooltip()) + { + auto pivotFormat = math::vec2_format_get(frame->pivot); + auto pivotString = std::format("Pivot: ({}, {})", pivotFormat, pivotFormat); + ImGui::Text(pivotString.c_str(), frame->pivot.x, frame->pivot.y); + ImGui::EndTooltip(); + } + } + + if (isEnd) document.change(Document::FRAMES); + break; + case tool::CROP: + if (!frame) break; + if (isBegin) document.snapshot("Frame Crop"); + + if (isMouseClicked) + { + cropAnchor = mousePos; + frame->crop = cropAnchor; + frame->size = vec2(); + } + if (isMouseDown) + { + auto [minPoint, maxPoint] = snap_rect(glm::min(cropAnchor, mousePos), glm::max(cropAnchor, mousePos)); + frame->crop = minPoint; + frame->size = maxPoint - minPoint; + } + if (isLeftPressed) frame->crop.x -= stepX; + if (isRightPressed) frame->crop.x += stepX; + if (isUpPressed) frame->crop.y -= stepY; + if (isDownPressed) frame->crop.y += stepY; + if (isDuring) + { + if (!isMouseDown) + { + auto minPoint = glm::min(frame->crop, frame->crop + frame->size); + auto maxPoint = glm::max(frame->crop, frame->crop + frame->size); + frame->crop = minPoint; + frame->size = maxPoint - minPoint; + if (isGridSnap) + { + auto [snapMin, snapMax] = snap_rect(frame->crop, frame->crop + frame->size); + frame->crop = snapMin; + frame->size = snapMax - snapMin; + } + } + if (ImGui::BeginTooltip()) + { + auto cropFormat = math::vec2_format_get(frame->crop); + auto sizeFormat = math::vec2_format_get(frame->size); + auto cropString = std::format("Crop: ({}, {})", cropFormat, cropFormat); + auto sizeString = std::format("Size: ({}, {})", sizeFormat, sizeFormat); + ImGui::Text(cropString.c_str(), frame->crop.x, frame->crop.y); + ImGui::Text(sizeString.c_str(), frame->size.x, frame->size.y); + ImGui::EndTooltip(); + } + } + if (isEnd) document.change(Document::FRAMES); + break; + case tool::DRAW: + case tool::ERASE: + { + if (!spritesheet) break; + auto color = useTool == tool::DRAW ? toolColor : vec4(); + if (isMouseClicked) document.snapshot(useTool == tool::DRAW ? "Draw" : "Erase"); + if (isMouseDown) spritesheet->texture.pixel_line(ivec2(previousMousePos), ivec2(mousePos), color); + if (isMouseReleased) document.change(Document::SPRITESHEETS); + break; + } + case tool::COLOR_PICKER: + { + if (isDuring) + { + auto position = to_vec2(ImGui::GetMousePos()); + toolColor = pixel_read(position, {settings.windowSize.x, settings.windowSize.y}); + if (ImGui::BeginTooltip()) + { + ImGui::ColorButton("##Color Picker Button", to_imvec4(toolColor)); + ImGui::EndTooltip(); + } + } + break; + } + default: + break; + } + + if (mouseWheel != 0 || isZoomIn || isZoomOut) + { + auto focus = mouseWheel != 0 ? vec2(mousePos) : vec2(); + if (auto spritesheet = document.spritesheet_get(); spritesheet && mouseWheel == 0) + focus = spritesheet->texture.size / 2; + + zoom_set(zoom, pan, focus, (mouseWheel > 0 || isZoomIn) ? zoomStep : -zoomStep); + } + } + } + ImGui::End(); + + if (!document.isSpritesheetEditorSet) + { + size = settings.editorSize; + zoom = settings.editorStartZoom; + center_view(); + document.isSpritesheetEditorSet = true; + } + + settings.editorSize = size; + settings.editorStartZoom = zoom; + } +} diff --git a/src/imgui/window/spritesheet_editor.h b/src/imgui/window/spritesheet_editor.h new file mode 100644 index 0000000..8c992fe --- /dev/null +++ b/src/imgui/window/spritesheet_editor.h @@ -0,0 +1,20 @@ +#pragma once + +#include "canvas.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class SpritesheetEditor : public Canvas + { + glm::vec2 mousePos{}; + glm::vec2 previousMousePos{}; + glm::vec2 cropAnchor{}; + + public: + SpritesheetEditor(); + void update(Manager&, Settings&, Resources&); + }; +} diff --git a/src/imgui/window/spritesheets.cpp b/src/imgui/window/spritesheets.cpp new file mode 100644 index 0000000..804690a --- /dev/null +++ b/src/imgui/window/spritesheets.cpp @@ -0,0 +1,307 @@ +#include "spritesheets.h" + +#include + +#include "document.h" +#include "toast.h" + +using namespace anm2ed::types; +using namespace anm2ed::resource; +using namespace glm; + +namespace anm2ed::imgui +{ + void Spritesheets::update(Manager& manager, Settings& settings, Resources& resources, Dialog& dialog, + Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& anm2 = document.anm2; + auto& selection = document.spritesheet.selection; + auto& unused = document.spritesheet.unused; + auto& hovered = document.spritesheet.hovered; + auto& reference = document.spritesheet.reference; + + hovered = -1; + + if (ImGui::Begin("Spritesheets", &settings.windowIsSpritesheets)) + { + auto style = ImGui::GetStyle(); + + auto context_menu = [&]() + { + auto copy = [&]() + { + if (!selection.empty()) + { + std::string clipboardText{}; + for (auto& id : selection) + clipboardText += anm2.content.spritesheets[id].to_string(id); + clipboard.set(clipboardText); + } + else if (hovered > -1) + clipboard.set(anm2.content.spritesheets[hovered].to_string(hovered)); + }; + + auto paste = [&](merge::Type type) + { + std::string errorString{}; + document.snapshot("Paste Spritesheet(s)"); + if (anm2.spritesheets_deserialize(clipboard.get(), document.directory_get(), type, &errorString)) + document.change(Document::SPRITESHEETS); + else + toasts.error(std::format("Failed to deserialize spritesheet(s): {}", errorString)); + }; + + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(merge::APPEND); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, true); + + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, !selection.empty() || hovered > -1)) copy(); + + if (ImGui::BeginMenu("Paste", !clipboard.is_empty())) + { + if (ImGui::MenuItem("Append", settings.shortcutPaste.c_str())) paste(merge::APPEND); + if (ImGui::MenuItem("Replace")) paste(merge::REPLACE); + + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + ImGui::PopStyleVar(2); + }; + + auto childSize = size_without_footer_get(2); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + if (ImGui::BeginChild("##Spritesheets Child", childSize, ImGuiChildFlags_Borders)) + { + auto spritesheetChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() * 4); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + + selection.start(anm2.content.spritesheets.size(), ImGuiMultiSelectFlags_ClearOnEscape); + + for (auto& [id, spritesheet] : anm2.content.spritesheets) + { + ImGui::PushID(id); + + if (ImGui::BeginChild("##Spritesheet Child", spritesheetChildSize, ImGuiChildFlags_Borders)) + { + auto isSelected = selection.contains(id); + auto isReferenced = id == reference; + auto cursorPos = ImGui::GetCursorPos(); + auto& texture = spritesheet.texture.is_valid() ? spritesheet.texture : resources.icons[icon::NONE]; + auto path = spritesheet.path.empty() ? anm2::NO_PATH : spritesheet.path.c_str(); + + ImGui::SetNextItemSelectionUserData(id); + ImGui::SetNextItemStorageID(id); + if (ImGui::Selectable("##Spritesheet Selectable", isSelected, 0, spritesheetChildSize)) reference = id; + if (ImGui::IsItemHovered()) hovered = id; + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + if (ImGui::BeginItemTooltip()) + { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + + auto viewport = ImGui::GetMainViewport(); + + auto textureSize = texture.size.x * texture.size.y > (viewport->Size.x * viewport->Size.y) * 0.5f + ? to_vec2(viewport->Size) * 0.5f + : vec2(texture.size); + auto aspectRatio = (float)texture.size.x / texture.size.y; + + if (textureSize.x / textureSize.y > aspectRatio) + textureSize.x = textureSize.y * aspectRatio; + else + textureSize.y = textureSize.x / aspectRatio; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + if (ImGui::BeginChild("##Spritesheet Tooltip Image Child", to_imvec2(textureSize), + ImGuiChildFlags_Borders)) + ImGui::Image(texture.id, ImGui::GetContentRegionAvail()); + ImGui::PopStyleVar(); + ImGui::EndChild(); + + ImGui::PopStyleVar(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("##Spritesheet Info Tooltip Child")) + { + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE); + ImGui::TextUnformatted(path); + ImGui::PopFont(); + ImGui::Text("ID: %d", id); + ImGui::Text("Size: %d x %d", texture.size.x, texture.size.y); + } + ImGui::EndChild(); + + ImGui::EndTooltip(); + } + ImGui::PopStyleVar(2); + + auto imageSize = to_imvec2(vec2(spritesheetChildSize.y)); + auto aspectRatio = (float)texture.size.x / texture.size.y; + + if (imageSize.x / imageSize.y > aspectRatio) + imageSize.x = imageSize.y * aspectRatio; + else + imageSize.y = imageSize.x / aspectRatio; + + ImGui::SetCursorPos(cursorPos); + ImGui::Image(texture.id, imageSize); + + ImGui::SetCursorPos( + ImVec2(spritesheetChildSize.y + style.ItemSpacing.x, + spritesheetChildSize.y - spritesheetChildSize.y / 2 - ImGui::GetTextLineHeight() / 2)); + + if (isReferenced) ImGui::PushFont(resources.fonts[font::ITALICS].get(), font::SIZE); + ImGui::Text(anm2::SPRITESHEET_FORMAT_C, id, path); + if (isReferenced) ImGui::PopFont(); + + context_menu(); + } + + ImGui::EndChild(); + + ImGui::PopID(); + } + + ImGui::PopStyleVar(2); + + context_menu(); + selection.finish(); + } + ImGui::EndChild(); + + auto rowOneWidgetSize = widget_size_with_row_get(4); + + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_OPEN); + set_item_tooltip_shortcut("Add a new spritesheet.", settings.shortcutAdd); + + if (dialog.is_selected(dialog::SPRITESHEET_OPEN)) + { + document.spritesheet_add(dialog.path); + dialog.reset(); + } + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + if (ImGui::Button("Reload", rowOneWidgetSize)) + { + auto reload = [&]() + { + for (auto& id : selection) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet.reload(document.directory_get()); + toasts.info(std::format("Reloaded spritesheet #{}: {}", id, spritesheet.path.string())); + } + }; + + DOCUMENT_EDIT(document, "Reload Spritesheet(s)", Document::SPRITESHEETS, reload()); + } + ImGui::SetItemTooltip("Reloads the selected spritesheets."); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.size() != 1); + { + if (ImGui::Button("Replace", rowOneWidgetSize)) dialog.file_open(dialog::SPRITESHEET_REPLACE); + ImGui::SetItemTooltip("Replace the selected spritesheet with a new one."); + } + ImGui::EndDisabled(); + + if (dialog.is_selected(dialog::SPRITESHEET_REPLACE)) + { + auto replace = [&]() + { + auto& id = *selection.begin(); + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + spritesheet = anm2::Spritesheet(document.directory_get(), dialog.path); + toasts.info(std::format("Replaced spritesheet #{}: {}", id, spritesheet.path.string())); + }; + + DOCUMENT_EDIT(document, "Replace Spritesheet", Document::SPRITESHEETS, replace()); + dialog.reset(); + } + + ImGui::SameLine(); + + ImGui::BeginDisabled(unused.empty()); + { + shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove Unused", rowOneWidgetSize)) + { + auto remove_unused = [&]() + { + for (auto& id : unused) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + toasts.info(std::format("Removed spritesheet #{}: {}", id, spritesheet.path.string())); + anm2.content.spritesheets.erase(id); + } + unused.clear(); + }; + + DOCUMENT_EDIT(document, "Remove Unused Spritesheets", Document::SPRITESHEETS, remove_unused()); + } + set_item_tooltip_shortcut("Remove all unused spritesheets (i.e., not used in any layer.).", + settings.shortcutRemove); + } + ImGui::EndDisabled(); + + auto rowTwoWidgetSize = widget_size_with_row_get(3); + + shortcut(settings.shortcutSelectAll); + ImGui::BeginDisabled(selection.size() == anm2.content.spritesheets.size()); + { + if (ImGui::Button("Select All", rowTwoWidgetSize)) + for (auto& id : anm2.content.spritesheets | std::views::keys) + selection.insert(id); + } + ImGui::EndDisabled(); + set_item_tooltip_shortcut("Select all spritesheets.", settings.shortcutSelectAll); + + ImGui::SameLine(); + + shortcut(settings.shortcutSelectNone); + ImGui::BeginDisabled(selection.empty()); + if (ImGui::Button("Select None", rowTwoWidgetSize)) selection.clear(); + set_item_tooltip_shortcut("Unselect all spritesheets.", settings.shortcutSelectNone); + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::BeginDisabled(selection.empty()); + { + if (ImGui::Button("Save", rowTwoWidgetSize)) + { + for (auto& id : selection) + { + anm2::Spritesheet& spritesheet = anm2.content.spritesheets[id]; + if (spritesheet.save(document.directory_get())) + toasts.info(std::format("Saved spritesheet #{}: {}", id, spritesheet.path.string())); + else + toasts.info(std::format("Unable to save spritesheet #{}: {}", id, spritesheet.path.string())); + } + } + } + ImGui::EndDisabled(); + ImGui::SetItemTooltip("Save the selected spritesheets."); + } + ImGui::End(); + } +} \ No newline at end of file diff --git a/src/imgui/window/spritesheets.h b/src/imgui/window/spritesheets.h new file mode 100644 index 0000000..f012e8b --- /dev/null +++ b/src/imgui/window/spritesheets.h @@ -0,0 +1,16 @@ +#pragma once + +#include "clipboard.h" +#include "dialog.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Spritesheets + { + public: + void update(Manager&, Settings&, Resources&, Dialog&, Clipboard& clipboard); + }; +} diff --git a/src/imgui/window/timeline.cpp b/src/imgui/window/timeline.cpp new file mode 100644 index 0000000..0558eba --- /dev/null +++ b/src/imgui/window/timeline.cpp @@ -0,0 +1,1011 @@ +#include "timeline.h" + +#include + +#include + +#include "toast.h" + +using namespace anm2ed::resource; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + constexpr auto COLOR_HIDDEN_MULTIPLIER = vec4(0.5f, 0.5f, 0.5f, 1.000f); + constexpr auto FRAME_TIMELINE_COLOR = ImVec4(0.106f, 0.184f, 0.278f, 1.000f); + constexpr auto FRAME_BORDER_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.15f); + constexpr auto FRAME_MULTIPLE_OVERLAY_COLOR = ImVec4(1.0f, 1.0f, 1.0f, 0.05f); + constexpr auto PLAYHEAD_LINE_THICKNESS = 4.0f; + + constexpr auto TEXT_MULTIPLE_COLOR = to_imvec4(color::WHITE); + constexpr auto PLAYHEAD_LINE_COLOR = to_imvec4(color::WHITE); + + constexpr auto FRAME_MULTIPLE = 5; + + constexpr auto HELP_FORMAT = R"(- Press {} to decrement time. +- Press {} to increment time. +- Press {} to shorten the selected frame, by one frame. +- Press {} to extend the selected frame, by one frame. +- Hold Alt while clicking a non-trigger frame to toggle interpolation.)"; + + void Timeline::update(Manager& manager, Settings& settings, Resources& resources, Clipboard& clipboard) + { + auto& document = *manager.get(); + auto& playback = document.playback; + auto& reference = document.reference; + auto animation = document.animation_get(); + + style = ImGui::GetStyle(); + + auto context_menu = [&]() + { + auto& hoveredFrame = document.hoveredFrame; + auto& anm2 = document.anm2; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + + auto copy = [&]() + { + if (auto frame = anm2.frame_get(hoveredFrame)) clipboard.set(frame->to_string(hoveredFrame.itemType)); + }; + + auto cut = [&]() + { + copy(); + auto frames_delete = [&]() + { + if (auto item = anm2.item_get(reference); item) + { + item->frames.erase(item->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + } + }; + + DOCUMENT_EDIT(document, "Cut Frame(s)", Document::FRAMES, frames_delete()); + }; + + auto paste = [&]() + { + if (auto item = document.item_get()) + { + document.snapshot("Paste Frame(s)"); + std::set indices{}; + std::string errorString{}; + auto start = reference.frameIndex + 1; + if (item->frames_deserialize(clipboard.get(), reference.itemType, start, indices, &errorString)) + document.change(Document::FRAMES); + else + toasts.error(std::format("Failed to deserialize frame(s): {}", errorString)); + } + else + toasts.error(std::format("Failed to deserialize frame(s): select an item first!")); + }; + + if (shortcut(settings.shortcutCut, shortcut::FOCUSED)) cut(); + if (shortcut(settings.shortcutCopy, shortcut::FOCUSED)) copy(); + if (shortcut(settings.shortcutPaste, shortcut::FOCUSED)) paste(); + + if (ImGui::BeginPopupContextWindow("##Context Menu", ImGuiPopupFlags_MouseButtonRight)) + { + if (ImGui::MenuItem("Cut", settings.shortcutCut.c_str(), false, hoveredFrame != anm2::Reference{})) cut(); + if (ImGui::MenuItem("Copy", settings.shortcutCopy.c_str(), false, hoveredFrame != anm2::Reference{})) copy(); + if (ImGui::MenuItem("Paste", nullptr, false, !clipboard.is_empty())) paste(); + ImGui::EndPopup(); + } + + ImGui::PopStyleVar(2); + }; + + auto item_child = [&](anm2::Type type, int id, int& index) + { + auto& anm2 = document.anm2; + + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; + auto isActive = reference.itemType == type && reference.itemID == id; + + auto label = type == anm2::LAYER ? std::format(anm2::LAYER_FORMAT, id, anm2.content.layers.at(id).name, + anm2.content.layers[id].spritesheetID) + : type == anm2::NULL_ ? std::format(anm2::NULL_FORMAT, id, anm2.content.nulls[id].name) + : anm2::TYPE_STRINGS[type]; + auto icon = anm2::TYPE_ICONS[type]; + auto color = to_imvec4(isActive ? anm2::TYPE_COLOR_ACTIVE[type] : anm2::TYPE_COLOR[type]); + color = !isVisible ? to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER) : color; + ImGui::PushStyleColor(ImGuiCol_ChildBg, color); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto itemSize = ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + + if (ImGui::BeginChild(label.c_str(), itemSize, ImGuiChildFlags_Borders)) + { + if (type != anm2::NONE) + { + anm2::Reference itemReference = {reference.animationIndex, type, id}; + + if (ImGui::IsWindowHovered()) + { + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) + { + switch (type) + { + case anm2::LAYER: + manager.layer_properties_open(id); + break; + case anm2::NULL_: + manager.null_properties_open(id); + default: + break; + } + } + + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) reference = itemReference; + } + + ImGui::Image(resources.icons[icon].id, icon_size_get()); + ImGui::SameLine(); + ImGui::TextUnformatted(label.c_str()); + + anm2::Item* itemPtr = animation->item_get(type, id); + bool& itemVisible = itemPtr->isVisible; + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + ImGui::SetCursorPos( + ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + int visibleIcon = itemVisible ? icon::VISIBLE : icon::INVISIBLE; + + if (ImGui::ImageButton("##Visible Toggle", resources.icons[visibleIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Item Visibility", Document::FRAMES, itemVisible = !itemVisible); + ImGui::SetItemTooltip(itemVisible ? "The item is shown. Press to hide." + : "The item is hidden. Press to show."); + + if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls.at(id); + auto& isShowRect = null.isShowRect; + + auto rectIcon = isShowRect ? icon::SHOW_RECT : icon::HIDE_RECT; + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + if (ImGui::ImageButton("##Rect Toggle", resources.icons[rectIcon].id, icon_size_get())) + DOCUMENT_EDIT(document, "Null Rect", Document::FRAMES, null.isShowRect = !null.isShowRect); + ImGui::SetItemTooltip(isShowRect ? "The null's rect is shown. Press to hide." + : "The null's rect is hidden. Press to show."); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + } + else + { + auto cursorPos = ImGui::GetCursorPos(); + auto& isShowUnused = settings.timelineIsShowUnused; + + ImGui::SetCursorPos( + ImVec2(itemSize.x - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4()); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + auto unusedIcon = isShowUnused ? icon::SHOW_UNUSED : icon::HIDE_UNUSED; + if (ImGui::ImageButton("##Unused Toggle", resources.icons[unusedIcon].id, icon_size_get())) + isShowUnused = !isShowUnused; + ImGui::SetItemTooltip(isShowUnused ? "Unused layers/nulls are shown. Press to hide." + : "Unused layers/nulls are hidden. Press to show."); + + auto& showLayersOnly = settings.timelineIsOnlyShowLayers; + auto layersIcon = showLayersOnly ? icon::SHOW_LAYERS : icon::HIDE_LAYERS; + + ImGui::SetCursorPos( + ImVec2(itemSize.x - (ImGui::GetTextLineHeightWithSpacing() * 2) - ImGui::GetStyle().ItemSpacing.x, + (itemSize.y - ImGui::GetTextLineHeightWithSpacing()) / 2)); + + if (ImGui::ImageButton("##Layers Toggle", resources.icons[layersIcon].id, icon_size_get())) + showLayersOnly = !showLayersOnly; + ImGui::SetItemTooltip(showLayersOnly ? "Only layers are visible. Press to show all items." + : "All items are visible. Press to only show layers."); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + + ImGui::SetCursorPos(cursorPos); + + ImGui::BeginDisabled(); + ImGui::Text("(?)"); + ImGui::SetItemTooltip("%s", + std::format(HELP_FORMAT, settings.shortcutNextFrame, settings.shortcutPreviousFrame, + settings.shortcutShortenFrame, settings.shortcutExtendFrame) + .c_str()); + ImGui::EndDisabled(); + } + } + ImGui::EndChild(); + ImGui::PopStyleColor(); + ImGui::PopStyleVar(2); + index++; + }; + + auto items_child = [&]() + { + auto itemsChildSize = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 15, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Items Child", itemsChildSize, ImGuiChildFlags_Borders)) + { + auto itemsListChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - + ImGui::GetTextLineHeightWithSpacing() - + ImGui::GetStyle().ItemSpacing.y * 2); + + if (ImGui::BeginChild("##Items List Child", itemsListChildSize, ImGuiChildFlags_Borders, + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar)) + { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 0.0f); + if (ImGui::BeginTable("##Item Table", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY)) + { + ImGui::GetCurrentWindow()->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Items"); + + auto item_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + item_child(type, id, index); + }; + + item_child_row(anm2::NONE); + + if (animation) + { + item_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (!settings.timelineIsShowUnused && animation->layerAnimations[id].frames.empty()) continue; + item_child_row(anm2::LAYER, id); + } + + for (auto& [id, nullAnimation] : animation->nullAnimations) + { + if (!settings.timelineIsShowUnused && nullAnimation.frames.empty()) continue; + item_child_row(anm2::NULL_, id); + } + + item_child_row(anm2::TRIGGER); + } + + if (isHorizontalScroll && ImGui::GetCurrentWindow()->ScrollbarY) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Dummy(ImVec2(0, style.ScrollbarSize)); + } + + ImGui::EndTable(); + } + ImGui::PopStyleVar(2); + } + ImGui::EndChild(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPosX() + style.WindowPadding.x, ImGui::GetCursorPosY())); + auto widgetSize = widget_size_with_row_get(2, ImGui::GetContentRegionAvail().x - style.WindowPadding.x); + + ImGui::BeginDisabled(!animation); + { + shortcut(settings.shortcutAdd); + if (ImGui::Button("Add", widgetSize)) propertiesPopup.open(); + set_item_tooltip_shortcut("Add a new item to the animation.", settings.shortcutAdd); + ImGui::SameLine(); + + ImGui::BeginDisabled(!document.item_get() && reference.itemType != anm2::LAYER && + reference.itemType != anm2::NULL_); + { + shortcut(settings.shortcutRemove); + if (ImGui::Button("Remove", widgetSize)) + { + auto remove = [&]() + { + animation->item_remove(reference.itemType, reference.itemID); + reference = {reference.animationIndex}; + }; + + DOCUMENT_EDIT(document, "Remove Item", Document::ITEMS, remove()); + } + set_item_tooltip_shortcut("Remove the selected item(s) from the animation.", settings.shortcutRemove); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + }; + + auto frame_child = [&](anm2::Type type, int id, int& index, float width) + { + auto& anm2 = document.anm2; + auto& hoveredFrame = document.hoveredFrame; + + auto item = animation ? animation->item_get(type, id) : nullptr; + auto isVisible = item ? item->isVisible : false; + auto& isOnlyShowLayers = settings.timelineIsOnlyShowLayers; + if (isOnlyShowLayers && type != anm2::LAYER) isVisible = false; + + auto color = to_imvec4(anm2::TYPE_COLOR[type]); + auto colorActive = to_imvec4(anm2::TYPE_COLOR_ACTIVE[type]); + auto colorHovered = to_imvec4(anm2::TYPE_COLOR_HOVERED[type]); + auto colorHidden = to_imvec4(to_vec4(color) * COLOR_HIDDEN_MULTIPLIER); + auto colorActiveHidden = to_imvec4(to_vec4(colorActive) * COLOR_HIDDEN_MULTIPLIER); + auto colorHoveredHidden = to_imvec4(to_vec4(colorHidden) * COLOR_HIDDEN_MULTIPLIER); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + auto childSize = ImVec2(width, ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + + ImGui::PopStyleVar(2); + + ImGui::PushID(index); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2()); + + if (ImGui::BeginChild("##Frames Child", childSize, ImGuiChildFlags_Borders)) + { + auto length = animation ? animation->frameNum : anm2.animations.length(); + auto frameSize = ImVec2(ImGui::GetTextLineHeight(), ImGui::GetContentRegionAvail().y); + auto framesSize = ImVec2(frameSize.x * length, frameSize.y); + auto cursorPos = ImGui::GetCursorPos(); + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + auto border = ImGui::GetStyle().FrameBorderSize; + auto borderLineLength = frameSize.y / 5; + auto scrollX = ImGui::GetScrollX(); + auto available = ImGui::GetContentRegionAvail(); + auto frameMin = std::max(0, (int)std::floor(scrollX / frameSize.x) - 1); + auto frameMax = std::min(anm2::FRAME_NUM_MAX, (int)std::ceil(scrollX + available.x / frameSize.x) + 1); + auto drawList = ImGui::GetWindowDrawList(); + pickerLineDrawList = drawList; + + if (type == anm2::NONE) + { + drawList->AddRectFilled(cursorScreenPos, + ImVec2(cursorScreenPos.x + framesSize.x, cursorScreenPos.y + framesSize.y), + ImGui::GetColorU32(FRAME_TIMELINE_COLOR)); + + for (int i = frameMin; i < frameMax; i++) + { + auto frameScreenPos = ImVec2(cursorScreenPos.x + frameSize.x * (float)i, cursorScreenPos.y); + + drawList->AddRect(frameScreenPos, ImVec2(frameScreenPos.x + border, frameScreenPos.y + borderLineLength), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + drawList->AddRect(ImVec2(frameScreenPos.x, frameScreenPos.y + frameSize.y - borderLineLength), + ImVec2(frameScreenPos.x + border, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_BORDER_COLOR)); + + if (i % FRAME_MULTIPLE == 0) + { + auto string = std::to_string(i); + auto textSize = ImGui::CalcTextSize(string.c_str()); + auto textPos = ImVec2(frameScreenPos.x + (frameSize.x - textSize.x) / 2, + frameScreenPos.y + (frameSize.y - textSize.y) / 2); + + drawList->AddRectFilled(frameScreenPos, + ImVec2(frameScreenPos.x + frameSize.x, frameScreenPos.y + frameSize.y), + ImGui::GetColorU32(FRAME_MULTIPLE_OVERLAY_COLOR)); + + drawList->AddText(textPos, ImGui::GetColorU32(TEXT_MULTIPLE_COLOR), string.c_str()); + } + } + + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDown(0)) + isDragging = true; + + if (isDragging) + { + auto childPos = ImGui::GetWindowPos(); + auto mousePos = ImGui::GetIO().MousePos; + auto localMousePos = ImVec2(mousePos.x - childPos.x, mousePos.y - childPos.y); + playback.time = floorf(localMousePos.x / frameSize.x); + reference.frameTime = playback.time; + } + + playback.clamp(settings.playbackIsClampPlayhead ? length : anm2::FRAME_NUM_MAX); + + if (ImGui::IsMouseReleased(0)) isDragging = false; + + ImGui::SetCursorPos(ImVec2(cursorPos.x + frameSize.x * floorf(playback.time), cursorPos.y)); + ImGui::Image(resources.icons[icon::PLAYHEAD].id, frameSize); + } + else if (animation) + { + anm2::Reference itemReference{reference.animationIndex, type, id}; + + ImGui::PushStyleColor(ImGuiCol_ButtonActive, isVisible ? colorActive : colorActiveHidden); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, isVisible ? colorHovered : colorHoveredHidden); + + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); + + float frameTime{}; + + for (auto [i, frame] : std::views::enumerate(item->frames)) + { + ImGui::PushID(i); + + auto frameReference = + anm2::Reference(itemReference.animationIndex, itemReference.itemType, itemReference.itemID, i); + auto isSelected = reference == frameReference; + vec2 frameMin = {frameTime * frameSize.x, cursorPos.y}; + vec2 frameMax = {frameMin.x + frame.delay * frameSize.x, frameMin.y + frameSize.y}; + auto buttonSize = to_imvec2(frameMax - frameMin); + auto buttonPos = ImVec2(cursorPos.x + frameMin.x, cursorPos.y); + ImGui::SetCursorPos(buttonPos); + ImGui::PushStyleColor(ImGuiCol_Button, isSelected && isVisible ? colorActive + : isSelected && !isVisible ? colorActiveHidden + : isVisible ? color + : colorHidden); + if (ImGui::Button("##Frame Button", buttonSize)) + { + if (type == anm2::LAYER) + { + document.spritesheet.reference = anm2.content.layers[id].spritesheetID; + document.layer.selection = {id}; + } + reference = frameReference; + reference.frameTime = frameTime; + + if (ImGui::IsKeyDown(ImGuiMod_Alt)) + DOCUMENT_EDIT(document, "Frame Interpolation", Document::FRAMES, + frame.isInterpolated = !frame.isInterpolated); + } + if (ImGui::IsItemHovered()) hoveredFrame = frameReference; + ImGui::PopStyleColor(); + auto icon = type == anm2::TRIGGER ? icon::TRIGGER + : frame.isInterpolated ? icon::INTERPOLATED + : icon::UNINTERPOLATED; + auto iconPos = ImVec2(cursorPos.x + (frameTime * frameSize.x), + cursorPos.y + (frameSize.y / 2) - (icon_size_get().y / 2)); + ImGui::SetCursorPos(iconPos); + ImGui::Image(resources.icons[icon].id, icon_size_get()); + + frameTime += frame.delay; + + ImGui::PopID(); + } + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(2); + } + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + index++; + ImGui::PopID(); + }; + + auto frames_child = [&]() + { + auto& anm2 = document.anm2; + + auto itemsChildWidth = ImGui::GetTextLineHeightWithSpacing() * 15; + + auto cursorPos = ImGui::GetCursorPos(); + ImGui::SetCursorPos(ImVec2(cursorPos.x + itemsChildWidth, cursorPos.y)); + + auto framesChildSize = ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y); + + if (ImGui::BeginChild("##Frames Child", framesChildSize, ImGuiChildFlags_Borders)) + { + auto viewListChildSize = + ImVec2(ImGui::GetContentRegionAvail().x, + ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - style.ItemSpacing.y * 2); + + auto childWidth = ImGui::GetContentRegionAvail().x > anm2.animations.length() * ImGui::GetTextLineHeight() + ? ImGui::GetContentRegionAvail().x + : anm2.animations.length() * ImGui::GetTextLineHeight(); + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2()); + if (ImGui::BeginChild("##Frames List Child", viewListChildSize, true, ImGuiWindowFlags_HorizontalScrollbar)) + { + auto cursorScreenPos = ImGui::GetCursorScreenPos(); + + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2()); + if (ImGui::BeginTable("##Frames List Table", 1, + ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) + { + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->Flags |= ImGuiWindowFlags_NoScrollWithMouse; + + scroll.x = ImGui::GetScrollX(); + scroll.y = ImGui::GetScrollY(); + + isHorizontalScroll = window->ScrollbarX; + + if (isWindowHovered) + { + auto& io = ImGui::GetIO(); + auto lineHeight = ImGui::GetTextLineHeightWithSpacing() * 2; + + scroll.x -= io.MouseWheelH * lineHeight; + scroll.y -= io.MouseWheel * lineHeight; + } + + ImGui::SetScrollX(scroll.x); + ImGui::SetScrollY(scroll.y); + + int index{}; + + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("##Frames"); + + auto frames_child_row = [&](anm2::Type type, int id = -1) + { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + frame_child(type, id, index, childWidth); + }; + + frames_child_row(anm2::NONE); + + if (animation) + { + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f); + + frames_child_row(anm2::ROOT); + + for (auto& id : animation->layerOrder) + { + if (auto itemPtr = animation->item_get(anm2::LAYER, id); itemPtr) + if (!settings.timelineIsShowUnused && itemPtr->frames.empty()) continue; + + frames_child_row(anm2::LAYER, id); + } + + for (auto& id : animation->nullAnimations | std::views::keys) + { + if (auto itemPtr = animation->item_get(anm2::NULL_, id); itemPtr) + if (!settings.timelineIsShowUnused && itemPtr->frames.empty()) continue; + frames_child_row(anm2::NULL_, id); + } + + frames_child_row(anm2::TRIGGER); + + ImGui::PopStyleVar(); + } + ImGui::EndTable(); + } + + ImDrawList* windowDrawList = ImGui::GetWindowDrawList(); + + auto frameSize = ImVec2(ImGui::GetTextLineHeight(), + ImGui::GetTextLineHeightWithSpacing() + (ImGui::GetStyle().WindowPadding.y * 2)); + auto linePos = ImVec2(cursorScreenPos.x + frameSize.x * floorf(playback.time) + (frameSize.x / 2) - scroll.x, + cursorScreenPos.y + frameSize.y); + auto lineSize = + ImVec2((PLAYHEAD_LINE_THICKNESS / 2.0f), + viewListChildSize.y - frameSize.y - (isHorizontalScroll ? ImGui::GetStyle().ScrollbarSize : 0.0f)); + + auto rectMin = windowDrawList->GetClipRectMin(); + auto rectMax = windowDrawList->GetClipRectMax(); + pickerLineDrawList->PushClipRect(rectMin, rectMax); + pickerLineDrawList->AddRectFilled(linePos, ImVec2(linePos.x + lineSize.x, linePos.y + lineSize.y), + ImGui::GetColorU32(PLAYHEAD_LINE_COLOR)); + pickerLineDrawList->PopClipRect(); + + ImGui::PopStyleVar(); + + context_menu(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.WindowPadding); + + ImGui::SetCursorPos( + ImVec2(ImGui::GetStyle().WindowPadding.x, ImGui::GetCursorPos().y + ImGui::GetStyle().ItemSpacing.y)); + + auto widgetSize = widget_size_with_row_get(10); + + ImGui::BeginDisabled(!animation); + { + auto label = playback.isPlaying ? "Pause" : "Play"; + auto tooltip = playback.isPlaying ? "Pause the animation." : "Play the animation."; + + shortcut(settings.shortcutPlayPause); + if (ImGui::Button(label, widgetSize)) playback.toggle(); + set_item_tooltip_shortcut(tooltip, settings.shortcutPlayPause); + + ImGui::SameLine(); + + auto itemPtr = document.item_get(); + + ImGui::BeginDisabled(!itemPtr); + { + shortcut(settings.shortcutAdd); + if (ImGui::Button("Insert Frame", widgetSize)) + { + auto insert_frame = [&]() + { + auto frame = document.frame_get(); + if (frame) + { + itemPtr->frames.insert(itemPtr->frames.begin() + reference.frameIndex, *frame); + reference.frameIndex++; + } + else if (!itemPtr->frames.empty()) + { + auto lastFrame = itemPtr->frames.back(); + itemPtr->frames.emplace_back(lastFrame); + reference.frameIndex = static_cast(itemPtr->frames.size()) - 1; + } + }; + + DOCUMENT_EDIT(document, "Insert Frame", Document::FRAMES, insert_frame()); + } + set_item_tooltip_shortcut("Insert a frame, based on the current selection.", settings.shortcutAdd); + + ImGui::SameLine(); + + ImGui::BeginDisabled(!document.frame_get()); + { + shortcut(settings.shortcutRemove); + if (ImGui::Button("Delete Frame", widgetSize)) + { + auto delete_frame = [&]() + { + itemPtr->frames.erase(itemPtr->frames.begin() + reference.frameIndex); + reference.frameIndex = glm::max(-1, --reference.frameIndex); + }; + + DOCUMENT_EDIT(document, "Delete Frame(s)", Document::FRAMES, delete_frame()); + } + set_item_tooltip_shortcut("Delete the selected frames.", settings.shortcutRemove); + + ImGui::SameLine(); + + if (ImGui::Button("Bake", widgetSize)) bakePopup.open(); + ImGui::SetItemTooltip("Turn interpolated frames into uninterpolated ones."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + if (ImGui::Button("Fit Animation Length", widgetSize)) animation->frameNum = animation->length(); + ImGui::SetItemTooltip("The animation length will be set to the effective length of the animation."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("Animation Length", animation ? &animation->frameNum : &dummy_value(), STEP, STEP_FAST, + !animation ? ImGuiInputTextFlags_DisplayEmptyRefVal : 0); + if (animation) animation->frameNum = clamp(animation->frameNum, anm2::FRAME_NUM_MIN, anm2::FRAME_NUM_MAX); + ImGui::SetItemTooltip("Set the animation's length."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Loop", animation ? &animation->isLoop : &dummy_value()); + ImGui::SetItemTooltip("Toggle the animation looping."); + } + ImGui::EndDisabled(); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::InputInt("FPS", &anm2.info.fps, 1, 5); + anm2.info.fps = clamp(anm2.info.fps, anm2::FPS_MIN, anm2::FPS_MAX); + ImGui::SetItemTooltip("Set the FPS of all animations."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + input_text_string("Author", &anm2.info.createdBy); + ImGui::SetItemTooltip("Set the author of the document."); + + ImGui::SameLine(); + + ImGui::SetNextItemWidth(widgetSize.x); + ImGui::Checkbox("Sound", &settings.timelineIsSound); + ImGui::SetItemTooltip("Toggle sounds playing with triggers.\nBind sounds to events in the Events window."); + + ImGui::PopStyleVar(); + } + ImGui::EndChild(); + + ImGui::SetCursorPos(cursorPos); + }; + + auto popups_fn = [&]() + { + auto item_properties_reset = [&]() + { + addItemName.clear(); + addItemSpritesheetID = {}; + addItemID = -1; + isUnusedItemsSet = false; + }; + + auto& anm2 = document.anm2; + + propertiesPopup.trigger(); + + if (ImGui::BeginPopupModal(propertiesPopup.label, &propertiesPopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto item_properties_close = [&]() + { + item_properties_reset(); + propertiesPopup.close(); + }; + + auto& type = settings.timelineAddItemType; + auto& locale = settings.timelineAddItemLocale; + auto& source = settings.timelineAddItemSource; + + if (!isUnusedItemsSet) + { + unusedItems = type == anm2::LAYER ? anm2.layers_unused(reference) + : type == anm2::NULL_ ? anm2.nulls_unused(reference) + : std::set{}; + + isUnusedItemsSet = true; + } + + auto footerSize = footer_size_get(); + auto optionsSize = child_size_get(11); + auto itemsSize = ImVec2(0, ImGui::GetContentRegionAvail().y - + (optionsSize.y + footerSize.y + ImGui::GetStyle().ItemSpacing.y * 4)); + if (ImGui::BeginChild("Options", optionsSize, ImGuiChildFlags_Borders)) + { + ImGui::SeparatorText("Type"); + + auto size = ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetFrameHeightWithSpacing()); + + if (ImGui::BeginChild("Type Layer", size)) + { + ImGui::RadioButton("Layer", &type, anm2::LAYER); + ImGui::SetItemTooltip( + "Layers are a basic visual element in an animation, used for displaying spritesheets."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Type Null", size)) + { + ImGui::RadioButton("Null", &type, anm2::NULL_); + ImGui::SetItemTooltip( + "Nulls are invisible elements in an animation, used for interfacing with a game engine."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Source"); + + bool isNewOnly = unusedItems.empty(); + if (isNewOnly) source = source::NEW; + + if (ImGui::BeginChild("Source New", size)) + { + ImGui::RadioButton("New", &source, source::NEW); + ImGui::SetItemTooltip("Create a new item to be used."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Source Existing", size)) + { + ImGui::BeginDisabled(isNewOnly); + ImGui::RadioButton("Existing", &source, source::EXISTING); + ImGui::EndDisabled(); + ImGui::SetItemTooltip("Use a pre-existing, presently unused item."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Locale"); + + if (ImGui::BeginChild("Locale Global", size)) + { + ImGui::RadioButton("Global", &locale, locale::GLOBAL); + ImGui::SetItemTooltip("The item will be inserted into all animations, if not already present."); + } + ImGui::EndChild(); + + ImGui::SameLine(); + + if (ImGui::BeginChild("Locale Local", size)) + { + ImGui::RadioButton("Local", &locale, locale::LOCAL); + ImGui::SetItemTooltip("The item will only be inserted into this animation."); + } + ImGui::EndChild(); + + ImGui::SeparatorText("Options"); + + ImGui::BeginDisabled(source == source::EXISTING); + { + input_text_string("Name", &addItemName); + ImGui::SetItemTooltip("Set the item's name."); + ImGui::BeginDisabled(type != anm2::LAYER); + { + combo_negative_one_indexed("Spritesheet", &addItemSpritesheetID, document.spritesheet.labels); + ImGui::SetItemTooltip("Set the layer item's spritesheet."); + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + } + ImGui::EndChild(); + + if (ImGui::BeginChild("Items", itemsSize, ImGuiChildFlags_Borders)) + { + if (animation && source == source::EXISTING) + { + for (auto id : unusedItems) + { + auto isSelected = addItemID == id; + + ImGui::PushID(id); + + if (type == anm2::LAYER) + { + auto& layer = anm2.content.layers[id]; + if (ImGui::Selectable( + std::format("#{} {} (Spritesheet: #{})", id, layer.name, layer.spritesheetID).c_str(), + isSelected)) + addItemID = id; + } + else if (type == anm2::NULL_) + { + auto& null = anm2.content.nulls[id]; + if (ImGui::Selectable(std::format("#{} {}", id, null.name).c_str(), isSelected)) addItemID = id; + } + + ImGui::PopID(); + } + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Add", widgetSize)) + { + anm2::Reference addReference{}; + + document.snapshot("Add Item"); + if (type == anm2::LAYER) + addReference = anm2.layer_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + addItemSpritesheetID - 1, (locale::Type)locale); + else if (type == anm2::NULL_) + addReference = anm2.null_animation_add({reference.animationIndex, anm2::LAYER, addItemID}, addItemName, + (locale::Type)locale); + + document.change(Document::ITEMS); + + reference = addReference; + + item_properties_close(); + } + ImGui::SetItemTooltip("Add the item, with the settings specified."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) item_properties_close(); + ImGui::SetItemTooltip("Cancel adding an item."); + + ImGui::EndPopup(); + } + + bakePopup.trigger(); + + if (ImGui::BeginPopupModal(bakePopup.label, &bakePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + auto& interval = settings.bakeInterval; + auto& isRoundRotation = settings.bakeIsRoundRotation; + auto& isRoundScale = settings.bakeIsRoundScale; + + auto frame = document.frame_get(); + + input_int_range("Interval", interval, anm2::FRAME_DELAY_MIN, frame ? frame->delay : anm2::FRAME_DELAY_MIN); + ImGui::SetItemTooltip("Set the maximum delay of each frame that will be baked."); + + ImGui::Checkbox("Round Rotation", &isRoundRotation); + ImGui::SetItemTooltip("Rotation will be rounded to the nearest whole number."); + + ImGui::Checkbox("Round Scale", &isRoundScale); + ImGui::SetItemTooltip("Scale will be rounded to the nearest whole number."); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Bake", widgetSize)) + { + if (auto itemPtr = document.item_get()) + DOCUMENT_EDIT(document, "Bake Frames", Document::FRAMES, + itemPtr->frames_bake(reference.frameIndex, interval, isRoundScale, isRoundRotation)); + bakePopup.close(); + } + ImGui::SetItemTooltip("Bake the selected frame(s) with the options selected."); + + ImGui::SameLine(); + + if (ImGui::Button("Cancel", widgetSize)) bakePopup.close(); + ImGui::SetItemTooltip("Cancel baking frames."); + + ImGui::EndPopup(); + } + }; + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2()); + if (ImGui::Begin("Timeline", &settings.windowIsTimeline)) + { + isWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); + frames_child(); + items_child(); + } + ImGui::PopStyleVar(); + ImGui::End(); + + popups_fn(); + + if (shortcut(settings.shortcutPlayPause, shortcut::GLOBAL)) playback.toggle(); + + if (animation) + { + if (chord_repeating(string_to_chord(settings.shortcutPreviousFrame))) + { + playback.decrement(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); + reference.frameTime = playback.time; + } + + if (chord_repeating(string_to_chord(settings.shortcutNextFrame))) + { + playback.increment(settings.playbackIsClampPlayhead ? animation->frameNum : anm2::FRAME_NUM_MAX); + reference.frameTime = playback.time; + } + } + + if (ImGui::IsKeyChordPressed(string_to_chord(settings.shortcutShortenFrame))) document.snapshot("Shorten Frame"); + if (chord_repeating(string_to_chord(settings.shortcutShortenFrame))) + { + if (auto frame = document.frame_get()) + { + frame->shorten(); + document.change(Document::FRAMES); + } + } + + if (ImGui::IsKeyChordPressed(string_to_chord(settings.shortcutExtendFrame))) document.snapshot("Extend Frame"); + if (chord_repeating(string_to_chord(settings.shortcutExtendFrame))) + { + if (auto frame = document.frame_get()) + { + frame->extend(); + document.change(Document::FRAMES); + } + } + } +} diff --git a/src/imgui/window/timeline.h b/src/imgui/window/timeline.h new file mode 100644 index 0000000..e1b41cc --- /dev/null +++ b/src/imgui/window/timeline.h @@ -0,0 +1,30 @@ +#pragma once + +#include "clipboard.h" +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Timeline + { + bool isDragging{}; + bool isWindowHovered{}; + bool isHorizontalScroll{}; + PopupHelper propertiesPopup{PopupHelper("Item Properties", POPUP_NORMAL)}; + PopupHelper bakePopup{PopupHelper("Bake", POPUP_TO_CONTENT)}; + std::string addItemName{}; + bool addItemIsRect{}; + int addItemID{-1}; + int addItemSpritesheetID{-1}; + bool isUnusedItemsSet{}; + std::set unusedItems{}; + glm::vec2 scroll{}; + ImDrawList* pickerLineDrawList{}; + ImGuiStyle style{}; + + public: + void update(Manager&, Settings&, Resources&, Clipboard&); + }; +} diff --git a/src/imgui/window/tools.cpp b/src/imgui/window/tools.cpp new file mode 100644 index 0000000..608806d --- /dev/null +++ b/src/imgui/window/tools.cpp @@ -0,0 +1,99 @@ + +#include "tools.h" + +#include + +#include "tool.h" +#include "types.h" + +using namespace anm2ed::resource; +using namespace anm2ed::types; +using namespace glm; + +namespace anm2ed::imgui +{ + void Tools::update(Manager& manager, Settings& settings, Resources& resources) + { + auto& document = *manager.get(); + + if (ImGui::Begin("Tools", &settings.windowIsTools)) + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2)); + + auto availableWidth = ImGui::GetContentRegionAvail().x; + auto size = vec2(ImGui::GetTextLineHeightWithSpacing() * 1.5f); + auto usedWidth = ImGui::GetStyle().WindowPadding.x; + + auto tool_use = [&](tool::Type type) + { + switch (type) + { + case tool::UNDO: + if (document.is_able_to_undo()) document.undo(); + break; + case tool::REDO: + if (document.is_able_to_redo()) document.redo(); + break; + case tool::COLOR: + colorEditPopup.open(); + break; + default: + settings.tool = type; + break; + } + }; + + for (int i = 0; i < tool::COUNT; i++) + { + auto& info = tool::INFO[i]; + auto isSelected = settings.tool == i; + + if (isSelected) ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive)); + + auto member = SHORTCUT_MEMBERS[info.shortcut]; + + if (shortcut(settings.*member, shortcut::GLOBAL_SET)) tool_use((tool::Type)i); + + if (i == tool::COLOR) + { + size += to_vec2(ImGui::GetStyle().FramePadding) * 2.0f; + if (ImGui::ColorButton(info.label, to_imvec4(settings.toolColor), ImGuiColorEditFlags_NoTooltip, + to_imvec2(size))) + tool_use((tool::Type)i); + + colorEditPosition = ImGui::GetCursorScreenPos(); + } + else + { + if (i == tool::UNDO) ImGui::BeginDisabled(!document.is_able_to_undo()); + if (i == tool::REDO) ImGui::BeginDisabled(!document.is_able_to_redo()); + if (ImGui::ImageButton(info.label, resources.icons[info.icon].id, to_imvec2(size))) tool_use((tool::Type)i); + if (i == tool::UNDO) ImGui::EndDisabled(); + if (i == tool::REDO) ImGui::EndDisabled(); + } + + auto widthIncrement = ImGui::GetItemRectSize().x + ImGui::GetStyle().ItemSpacing.x; + usedWidth += widthIncrement; + + if (usedWidth + widthIncrement < availableWidth) + ImGui::SameLine(); + else + usedWidth = ImGui::GetStyle().WindowPadding.x; + set_item_tooltip_shortcut(info.tooltip, settings.*SHORTCUT_MEMBERS[info.shortcut]); + + if (isSelected) ImGui::PopStyleColor(); + } + + ImGui::PopStyleVar(); + + colorEditPopup.trigger(); + + if (ImGui::BeginPopup(colorEditPopup.label)) + { + ImGui::ColorPicker4(colorEditPopup.label, value_ptr(settings.toolColor)); + ImGui::EndPopup(); + } + } + ImGui::End(); + } +} diff --git a/src/imgui/window/tools.h b/src/imgui/window/tools.h new file mode 100644 index 0000000..ad1ea2c --- /dev/null +++ b/src/imgui/window/tools.h @@ -0,0 +1,19 @@ +#pragma once + +#include "manager.h" +#include "resources.h" +#include "settings.h" + +namespace anm2ed::imgui +{ + class Tools + { + bool isOpenColorEdit{}; + ImVec2 colorEditPosition{}; + + PopupHelper colorEditPopup{PopupHelper("##Color Edit", POPUP_TO_CONTENT, POPUP_BY_ITEM)}; + + public: + void update(Manager&, Settings&, Resources&); + }; +} diff --git a/src/imgui/window/welcome.cpp b/src/imgui/window/welcome.cpp new file mode 100644 index 0000000..b9d997f --- /dev/null +++ b/src/imgui/window/welcome.cpp @@ -0,0 +1,100 @@ +#include "welcome.h" + +#include + +using namespace anm2ed::resource; + +namespace anm2ed::imgui +{ + void Welcome::update(Manager& manager, Resources& resources, Dialog& dialog, Taskbar& taskbar, Documents& documents) + { + auto viewport = ImGui::GetMainViewport(); + auto windowHeight = viewport->Size.y - taskbar.height - documents.height; + + ImGui::SetNextWindowViewport(viewport->ID); + ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + taskbar.height + documents.height)); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, windowHeight)); + + if (ImGui::Begin("Welcome", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse)) + { + + ImGui::PushFont(resources.fonts[font::BOLD].get(), font::SIZE_LARGE); + ImGui::TextUnformatted("Anm2Ed"); + ImGui::PopFont(); + + ImGui::TextUnformatted("Select a recent file or open a new or existing document. You can also drag and drop " + "files into the window to open them."); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("New", widgetSize)) dialog.file_open(dialog::ANM2_NEW); // handled in taskbar.cpp + ImGui::SameLine(); + if (ImGui::Button("Open", widgetSize)) dialog.file_open(dialog::ANM2_OPEN); // handled in taskbar.cpp + + if (ImGui::BeginChild("##Recent Files Child", {}, ImGuiChildFlags_Borders)) + { + for (auto [i, file] : std::views::enumerate(manager.recentFiles)) + { + ImGui::PushID(i); + + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + + if (ImGui::Selectable(label.c_str())) + { + manager.open(file); + ImGui::PopID(); + break; + } + + ImGui::PopID(); + } + } + ImGui::EndChild(); + } + ImGui::End(); + + if (!manager.autosaveFiles.empty() && !restorePopup.is_open()) restorePopup.open(); + + restorePopup.trigger(); + + if (ImGui::BeginPopupModal(restorePopup.label, &restorePopup.isOpen, ImGuiWindowFlags_NoResize)) + { + ImGui::TextUnformatted("Autosaved documents detected. Would you like to restore them?"); + + auto childSize = child_size_get(5); + + if (ImGui::BeginChild("##Restore Files Child", childSize, ImGuiChildFlags_Borders, + ImGuiWindowFlags_HorizontalScrollbar)) + { + for (auto& file : manager.autosaveFiles) + { + auto label = std::format(FILE_LABEL_FORMAT, file.filename().string(), file.string()); + ImGui::TextUnformatted(label.c_str()); + } + } + ImGui::EndChild(); + + auto widgetSize = widget_size_with_row_get(2); + + if (ImGui::Button("Yes", widgetSize)) + { + manager.autosave_files_open(); + restorePopup.close(); + } + + ImGui::SameLine(); + + if (ImGui::Button("No", widgetSize)) + { + manager.autosave_files_clear(); + restorePopup.close(); + } + + ImGui::EndPopup(); + } + } + +} diff --git a/src/imgui/window/welcome.h b/src/imgui/window/welcome.h new file mode 100644 index 0000000..5a7d3f7 --- /dev/null +++ b/src/imgui/window/welcome.h @@ -0,0 +1,16 @@ +#pragma once + +#include "documents.h" +#include "manager.h" +#include "taskbar.h" + +namespace anm2ed::imgui +{ + class Welcome + { + PopupHelper restorePopup{PopupHelper("Restore", imgui::POPUP_SMALL_NO_HEIGHT)}; + + public: + void update(Manager&, Resources&, Dialog&, Taskbar&, Documents&); + }; +}; \ No newline at end of file diff --git a/src/loader.cpp b/src/loader.cpp new file mode 100644 index 0000000..f5ae413 --- /dev/null +++ b/src/loader.cpp @@ -0,0 +1,249 @@ +#include "loader.h" + +#include + +#include +#include + +#include + +#include "filesystem_.h" +#include "log.h" + +#include "socket.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed +{ + constexpr auto SOCKET_ADDRESS = "127.0.0.1"; + constexpr auto SOCKET_PORT = 11414; + + namespace + { + bool socket_paths_send(Socket& socket, const std::vector& paths) + { + uint32_t count = htonl(static_cast(paths.size())); + if (!socket.send(&count, sizeof(count))) return false; + + for (const auto& path : paths) + { + uint32_t length = htonl(static_cast(path.size())); + if (!socket.send(&length, sizeof(length))) return false; + if (!path.empty() && !socket.send(path.data(), path.size())) return false; + } + + return true; + } + + std::vector socket_paths_receive(Socket& socket) + { + uint32_t count{}; + if (!socket.receive(&count, sizeof(count))) return {}; + count = ntohl(count); + + std::vector paths; + paths.reserve(count); + + for (uint32_t i = 0; i < count; ++i) + { + uint32_t length{}; + if (!socket.receive(&length, sizeof(length))) return {}; + length = ntohl(length); + + std::string path(length, '\0'); + if (length > 0 && !socket.receive(path.data(), length)) return {}; + paths.emplace_back(std::move(path)); + } + + return paths; + } + } + + std::string Loader::settings_path() + { + return filesystem::path_preferences_get() + "settings.ini"; + } + + Loader::Loader(int argc, const char** argv) + { + for (int i = 1; i < argc; i++) + arguments.emplace_back(argv[i]); + + Socket testSocket; + if (!testSocket.open(SERVER)) + logger.warning(std::format("Failed to open socket; single instancing will not work.")); + + bool isPrimaryInstance = false; + + if (testSocket.bind({SOCKET_ADDRESS, SOCKET_PORT})) + { + socket = std::move(testSocket); + + if (!socket.listen()) + logger.warning("Could not listen on socket; single instancing disabled."); + else + { + isPrimaryInstance = true; + isSocketThread = true; + logger.info(std::format("Opened socket at {}:{}", SOCKET_ADDRESS, SOCKET_PORT)); + } + } + else + { + logger.info(std::format("Existing instance of program exists; passing arguments...")); + Socket clientSocket; + if (!clientSocket.open(CLIENT)) + logger.warning("Could not open client socket to forward arguments."); + else if (!clientSocket.connect({SOCKET_ADDRESS, SOCKET_PORT})) + logger.warning("Could not connect to existing instance."); + else if (!socket_paths_send(clientSocket, arguments)) + logger.warning("Failed to transfer arguments to existing instance."); + else + logger.info("Sent arguments to existing instance. Exiting."); + + if (!isPrimaryInstance) + { + isError = true; + return; + } + } + + settings = Settings(settings_path()); + + if (!SDL_Init(SDL_INIT_VIDEO)) + { + logger.fatal(std::format("Could not initialize SDL! {}", SDL_GetError())); + isError = true; + return; + } + + logger.info("Initialized SDL"); + + if (!MIX_Init()) + logger.warning(std::format("Could not initialize SDL_mixer! {}", SDL_GetError())); + else + logger.info("Initialized SDL_mixer"); + + window = SDL_CreateWindow("Anm2Ed", settings.windowSize.x, settings.windowSize.y, + SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + + glContext = SDL_GL_CreateContext(window); + + if (!glContext) + { + logger.fatal(std::format("Could not initialize OpenGL context! {}", SDL_GetError())); + isError = true; + return; + } + + if (!gladLoadGLLoader((GLADloadproc)(SDL_GL_GetProcAddress))) + { + logger.fatal(std::format("Could not initialize OpenGL!")); + isError = true; + return; + } + + logger.info(std::format("Initialized OpenGL {}", (const char*)glGetString(GL_VERSION))); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glLineWidth(2.0f); + glDisable(GL_MULTISAMPLE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LINE_SMOOTH); + glClearColor(color::BLACK.r, color::BLACK.g, color::BLACK.b, color::BLACK.a); + + IMGUI_CHECKVERSION(); + if (!ImGui::CreateContext()) + { + logger.fatal("Could not initialize Dear ImGui!"); + isError = true; + return; + } + + logger.info("Initialized Dear ImGui"); + + ImGui::StyleColorsDark(); + + ImGui_ImplSDL3_InitForOpenGL(window, glContext); + ImGui_ImplOpenGL3_Init("#version 330"); + + ImGuiIO& io = ImGui::GetIO(); + io.IniFilename = nullptr; + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; + io.ConfigWindowsMoveFromTitleBarOnly = true; + + ImGui::LoadIniSettingsFromDisk(settings_path().c_str()); + + if (isSocketThread) + { + isSocketRunning = true; + socketThread = std::thread( + [this]() + { + while (isSocketRunning) + { + auto client = socket.accept(); + if (!client.is_valid()) + { + if (!isSocketRunning) break; + continue; + } + + auto paths = socket_paths_receive(client); + for (auto& path : paths) + { + if (path.empty()) continue; + SDL_Event event{}; + event.type = SDL_EVENT_DROP_FILE; + event.drop.data = SDL_strdup(path.c_str()); + event.drop.windowID = window ? SDL_GetWindowID(window) : 0; + SDL_PushEvent(&event); + } + } + }); + } + } + + Loader::~Loader() + { + if (isSocketThread) + { + isSocketRunning = false; + + if (socket.is_valid()) + { + Socket wakeSocket; + if (wakeSocket.open(CLIENT) && wakeSocket.connect({SOCKET_ADDRESS, SOCKET_PORT})) + socket_paths_send(wakeSocket, {}); + } + + socket.close(); + if (socketThread.joinable()) socketThread.join(); + } + + if (ImGui::GetCurrentContext()) + { + settings.save(settings_path(), ImGui::SaveIniSettingsToMemory(nullptr)); + + ImGui_ImplSDL3_Shutdown(); + ImGui_ImplOpenGL3_Shutdown(); + ImGui::DestroyContext(); + } + + MIX_Quit(); + + if (SDL_WasInit(0)) + { + SDL_GL_DestroyContext(glContext); + SDL_DestroyWindow(window); + SDL_Quit(); + } + } +} diff --git a/src/loader.h b/src/loader.h new file mode 100644 index 0000000..3a2c1d5 --- /dev/null +++ b/src/loader.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "settings.h" +#include "socket.h" + +namespace anm2ed +{ + class Loader + { + std::string settings_path(); + + public: + Socket socket{}; + std::thread socketThread{}; + std::atomic_bool isSocketRunning{}; + SDL_Window* window{}; + SDL_GLContext glContext{}; + Settings settings; + std::vector arguments; + bool isError{}; + bool isSocketThread{}; + + Loader(int, const char**); + ~Loader(); + }; +} diff --git a/src/log.cpp b/src/log.cpp index 537d166..4aba110 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -1,56 +1,63 @@ #include "log.h" -inline std::ofstream logFile; +#include -std::string log_path_get(void) +#include "filesystem_.h" +#include "time_.h" + +using namespace anm2ed::util; + +namespace anm2ed { - return preferences_path_get() + LOG_PATH; + void Logger::write(const Level level, const std::string& message) + { + std::string formatted = std::format("{} {} {}", time::get("(%d-%B-%Y %I:%M:%S)"), LEVEL_STRINGS[level], message); + std::println("{}", formatted); + if (file.is_open()) file << formatted << '\n' << std::flush; + } + + void Logger::info(const std::string& message) + { + write(INFO, message); + } + + void Logger::warning(const std::string& message) + { + write(WARNING, message); + } + + void Logger::error(const std::string& message) + { + write(ERROR, message); + } + + void Logger::fatal(const std::string& message) + { + write(FATAL, message); + } + + void Logger::command(const std::string& message) + { + write(COMMAND, message); + } + + void Logger::open(const std::filesystem::path& path) + { + file.open(path, std::ios::out | std::ios::app); + } + + Logger::Logger() + { + open(filesystem::path_preferences_get() + "log.txt"); + info("Initializing Anm2Ed"); + } + + Logger::~Logger() + { + info("Exiting Anm2Ed"); + if (file.is_open()) file.close(); + } + } -void log_write(const std::string& string) -{ - std::println("{}", string); - - if (logFile.is_open()) - { - logFile << string << '\n'; - logFile.flush(); - } -} - -void log_init(void) -{ - std::string logFilepath = log_path_get(); - logFile.open(logFilepath, std::ios::out | std::ios::trunc); - if (!logFile) std::println("{}", std::format(LOG_INIT_ERROR, logFilepath)); -} - -void log_error(const std::string& error) -{ - log_write(LOG_ERROR_FORMAT + error); -} - -void log_info(const std::string& info) -{ - log_write(LOG_INFO_FORMAT + info); -} - -void log_warning(const std::string& warning) -{ - log_write(LOG_WARNING_FORMAT + warning); -} - -void log_imgui(const std::string& imgui) -{ - log_write(LOG_IMGUI_FORMAT + imgui); -} - -void log_command(const std::string& command) -{ - log_write(LOG_COMMAND_FORMAT + command); -} - -void log_free(void) -{ - logFile.close(); -} \ No newline at end of file +anm2ed::Logger logger; diff --git a/src/log.h b/src/log.h index 3ac20d9..f1ee6fc 100644 --- a/src/log.h +++ b/src/log.h @@ -1,21 +1,47 @@ #pragma once -#include "COMMON.h" +#include +#include -#define LOG_WARNING_FORMAT "[WARNING] " -#define LOG_ERROR_FORMAT "[ERROR] " -#define LOG_INFO_FORMAT "[INFO] " -#define LOG_IMGUI_FORMAT "[IMGUI] " -#define LOG_INIT_ERROR "[ERROR] Failed to open log file: {}" -#define LOG_COMMAND_FORMAT "[COMMAND] " -#define LOG_PATH "log.txt" +namespace anm2ed +{ +#define LEVELS \ + X(INFO, "[INFO]") \ + X(WARNING, "[WARNING]") \ + X(ERROR, "[ERROR]") \ + X(FATAL, "[FATAL]") \ + X(COMMAND, "[COMMAND]") -std::string log_path_get(void); -void log_init(void); -void log_write(const std::string& file); -void log_error(const std::string& error); -void log_info(const std::string& info); -void log_warning(const std::string& warning); -void log_imgui(const std::string& imgui); -void log_command(const std::string& command); -void log_free(void); \ No newline at end of file + enum Level + { +#define X(symbol, string) symbol, + LEVELS +#undef X + }; + + constexpr std::string_view LEVEL_STRINGS[] = { +#define X(symbol, string) string, + LEVELS +#undef X + }; +#undef LEVELS + + class Logger + { + std::ofstream file{}; + + public: + void write(const Level, const std::string&); + void info(const std::string&); + void warning(const std::string&); + void error(const std::string&); + void fatal(const std::string&); + void command(const std::string&); + void open(const std::filesystem::path&); + Logger(); + ~Logger(); + }; + +} + +extern anm2ed::Logger logger; diff --git a/src/main.cpp b/src/main.cpp index 42cffed..ea7d4da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,61 +1,16 @@ -#include "main.h" +#include "loader.h" +#include "state.h" -static bool _anm2_rescale(const std::string& file, f32 scale) +int main(int argc, const char** argv) { - Anm2 anm2; + anm2ed::Loader loader(argc, argv); - if (!anm2_deserialize(&anm2, file, false)) return false; - anm2_scale(&anm2, scale); - return anm2_serialize(&anm2, file); + if (loader.isError) return EXIT_FAILURE; + + anm2ed::State state(loader.window, loader.arguments); + + while (!state.isQuit) + state.loop(loader.window, loader.settings); + + return EXIT_SUCCESS; } - -s32 -main(s32 argc, char* argv[]) -{ - State state; - - log_init(); - - if (argc > 0 && argv[1]) - { - if (std::string(argv[1]) == ARGUMENT_RESCALE) - { - if (argv[2] && argv[3]) - { - if (_anm2_rescale(std::string(argv[2]), atof(argv[3]))) - { - log_info(std::format(ARGUMENT_RESCALE_ANM2_INFO, argv[2], argv[3])); - return EXIT_SUCCESS; - } - else - log_error(ARGUMENT_RESCALE_ANM2_ERROR); - } - else - log_error(ARGUMENT_RESCALE_ARGUMENT_ERROR); - - return EXIT_FAILURE; - } - else if (std::string(argv[1]) == ARGUMENT_TEST && argv[2]) - { - if (anm2_deserialize(&state.anm2, std::string(argv[2]), false)) return EXIT_SUCCESS; - return EXIT_FAILURE; - } - else if (std::string(argv[1]) == ARGUMENT_TEST_GL && argv[2]) - { - if (!sdl_init(&state, true)) return EXIT_FAILURE; - if (anm2_deserialize(&state.anm2, std::string(argv[2]))) return EXIT_SUCCESS; - return EXIT_FAILURE; - } - else - if (argv[1]) state.argument = argv[1]; - } - - init(&state); - - while (state.isRunning) - loop(&state); - - quit(&state); - - return EXIT_SUCCESS; -} \ No newline at end of file diff --git a/src/main.h b/src/main.h deleted file mode 100644 index 2e53307..0000000 --- a/src/main.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -#define ARGUMENT_TEST "--test" -#define ARGUMENT_TEST_GL "--test-gl" - -#define ARGUMENT_RESCALE "--rescale" -#define ARGUMENT_RESCALE_ARGUMENT_ERROR "--rescale: specify both anm2 and scale arguments" -#define ARGUMENT_RESCALE_ANM2_ERROR "Unable to rescale anm2 {} by value {}. Make sure the file is valid." -#define ARGUMENT_RESCALE_ANM2_INFO "Scaled anm2 {} by {}" - -#include "state.h" \ No newline at end of file diff --git a/src/manager.cpp b/src/manager.cpp new file mode 100644 index 0000000..016730e --- /dev/null +++ b/src/manager.cpp @@ -0,0 +1,285 @@ +#include "manager.h" + +#include + +#include "filesystem_.h" +#include "log.h" +#include "toast.h" +#include "vector_.h" + +using namespace anm2ed::types; +using namespace anm2ed::util; + +namespace anm2ed +{ + constexpr std::size_t RECENT_LIMIT = 10; + + std::filesystem::path Manager::recent_files_path_get() { return filesystem::path_preferences_get() + "recent.txt"; } + std::filesystem::path Manager::autosave_path_get() { return filesystem::path_preferences_get() + "autosave.txt"; } + std::filesystem::path Manager::autosave_directory_get() { return filesystem::path_preferences_get() + "autosave"; } + + Manager::Manager() + { + recent_files_load(); + autosave_files_load(); + } + + Document* Manager::get(int index) { return vector::find(documents, index > -1 ? index : selected); } + + void Manager::open(const std::string& path, bool isNew, bool isRecent) + { + std::string errorString{}; + documents.emplace_back(path, isNew, &errorString); + + auto& document = documents.back(); + if (!document.is_valid()) + { + documents.pop_back(); + toasts.error(std::format("Failed to open document: {} ({})", path, errorString)); + return; + } + + if (isRecent) + { + recentFiles.erase(std::remove(recentFiles.begin(), recentFiles.end(), path), recentFiles.end()); + recentFiles.insert(recentFiles.begin(), path); + + if (recentFiles.size() > RECENT_LIMIT) recentFiles.resize(RECENT_LIMIT); + + recent_files_write(); + } + + selected = (int)documents.size() - 1; + pendingSelected = selected; + toasts.info(std::format("Opened document: {}", path)); + } + + void Manager::new_(const std::string& path) { open(path, true); } + + void Manager::save(int index, const std::string& path) + { + if (auto document = get(index); document) + { + std::string errorString{}; + document->path = !path.empty() ? path : document->path.string(); + document->save(document->path, &errorString); + } + } + + void Manager::save(const std::string& path) { save(selected, path); } + + void Manager::autosave(Document& document) + { + std::string errorString{}; + auto autosavePath = document.autosave_path_get(); + document.autosave(&errorString); + + autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), autosavePath), autosaveFiles.end()); + autosaveFiles.insert(autosaveFiles.begin(), autosavePath); + + autosave_files_write(); + } + + void Manager::close(int index) + { + if (!vector::in_bounds(documents, index)) return; + + autosaveFiles.erase(std::remove(autosaveFiles.begin(), autosaveFiles.end(), get()->autosave_path_get()), + autosaveFiles.end()); + autosave_files_write(); + + documents.erase(documents.begin() + index); + + if (documents.empty()) + { + selected = -1; + pendingSelected = -1; + return; + } + + if (selected >= index) selected = std::max(0, selected - 1); + + selected = std::clamp(selected, 0, (int)documents.size() - 1); + pendingSelected = selected; + + if (selected >= 0 && selected < (int)documents.size()) documents[selected].change(Document::ALL); + } + + void Manager::set(int index) + { + if (documents.empty()) + { + selected = -1; + pendingSelected = -1; + return; + } + + index = std::clamp(index, 0, (int)documents.size() - 1); + selected = index; + + if (auto document = get()) document->change(Document::ALL); + } + + void Manager::layer_properties_open(int id) + { + if (auto document = get(); document) + { + if (id == -1) + editLayer = anm2::Layer(); + else + editLayer = document->anm2.content.layers.at(id); + + document->layer.reference = id; + + layerPropertiesPopup.open(); + } + } + + void Manager::layer_properties_trigger() { layerPropertiesPopup.trigger(); } + + void Manager::layer_properties_end() { layerPropertiesPopup.end(); } + + void Manager::layer_properties_close() + { + editLayer = anm2::Layer(); + layerPropertiesPopup.close(); + } + + void Manager::null_properties_open(int id) + { + if (auto document = get(); document) + { + if (id == -1) + editNull = anm2::Null(); + else + editNull = document->anm2.content.nulls.at(id); + + document->null.reference = id; + + nullPropertiesPopup.open(); + } + } + + void Manager::null_properties_trigger() { nullPropertiesPopup.trigger(); } + + void Manager::null_properties_end() { nullPropertiesPopup.end(); } + + void Manager::null_properties_close() + { + editNull = anm2::Null(); + nullPropertiesPopup.close(); + } + + void Manager::recent_files_load() + { + auto path = recent_files_path_get(); + + std::ifstream file(path); + if (!file) + { + logger.warning(std::format("Could not load recent files from: {}. Skipping...", path.string())); + return; + } + + logger.info(std::format("Loading recent files from: {}", path.string())); + + std::string line{}; + + while (std::getline(file, line)) + { + if (line.empty()) continue; + if (std::find(recentFiles.begin(), recentFiles.end(), line) != recentFiles.end()) continue; + recentFiles.emplace_back(line); + } + } + + void Manager::recent_files_write() + { + auto path = recent_files_path_get(); + + std::ofstream file; + file.open(path, std::ofstream::out | std::ofstream::trunc); + + if (!file.is_open()) + { + logger.warning(std::format("Could not write recent files to: {}. Skipping...", path.string())); + return; + } + + for (auto& path : recentFiles) + file << path.string() << '\n'; + } + + void Manager::recent_files_clear() + { + recentFiles.clear(); + recent_files_write(); + } + + void Manager::autosave_files_open() + { + for (auto& path : autosaveFiles) + { + auto fileName = path.filename().string(); + if (!fileName.empty() && fileName.front() == '.') fileName.erase(fileName.begin()); + + auto restorePath = path.parent_path() / fileName; + restorePath.replace_extension(""); + open(path.string(), false, false); + + if (auto document = get()) + { + document->isForceDirty = true; + document->path = restorePath; + document->change(Document::ALL); + } + } + + autosave_files_clear(); + } + + void Manager::autosave_files_load() + { + auto path = autosave_path_get(); + + std::ifstream file(path); + if (!file) + { + logger.warning(std::format("Could not load autosave files from: {}. Skipping...", path.string())); + return; + } + + logger.info(std::format("Loading autosave files from: {}", path.string())); + + std::string line{}; + + while (std::getline(file, line)) + { + if (line.empty()) continue; + if (std::find(autosaveFiles.begin(), autosaveFiles.end(), line) != autosaveFiles.end()) continue; + autosaveFiles.emplace_back(line); + } + } + + void Manager::autosave_files_write() + { + std::ofstream autosaveWriteFile; + autosaveWriteFile.open(autosave_path_get(), std::ofstream::out | std::ofstream::trunc); + + for (auto& path : autosaveFiles) + autosaveWriteFile << path.string() << "\n"; + + autosaveWriteFile.close(); + } + + void Manager::autosave_files_clear() + { + for (auto& path : autosaveFiles) + std::filesystem::remove(path); + + autosaveFiles.clear(); + autosave_files_write(); + } + + Manager::~Manager() { autosave_files_clear(); } +} diff --git a/src/manager.h b/src/manager.h new file mode 100644 index 0000000..485b309 --- /dev/null +++ b/src/manager.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +#include "document.h" + +namespace anm2ed +{ + constexpr auto FILE_LABEL_FORMAT = "{} [{}]"; + + class Manager + { + std::filesystem::path recent_files_path_get(); + std::filesystem::path autosave_path_get(); + + public: + std::vector documents{}; + std::vector recentFiles{}; + std::vector autosaveFiles{}; + + int selected{-1}; + int pendingSelected{-1}; + + bool isRecording{}; + bool isRecordingStart{}; + int recordingStart{}; + int recordingEnd{}; + bool isRecordingRange{}; + + anm2::Layer editLayer{}; + imgui::PopupHelper layerPropertiesPopup{imgui::PopupHelper("Layer Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; + + anm2::Null editNull{}; + imgui::PopupHelper nullPropertiesPopup{imgui::PopupHelper("Null Properties", imgui::POPUP_SMALL_NO_HEIGHT)}; + + imgui::PopupHelper progressPopup{imgui::PopupHelper("Rendering...", imgui::POPUP_SMALL_NO_HEIGHT)}; + + Manager(); + ~Manager(); + + Document* get(int = -1); + void open(const std::string&, bool = false, bool = true); + void new_(const std::string&); + void save(int, const std::string& = {}); + void save(const std::string& = {}); + void autosave(Document&); + void set(int); + void close(int); + void layer_properties_open(int = -1); + void layer_properties_trigger(); + void layer_properties_end(); + void layer_properties_close(); + void null_properties_open(int = -1); + void null_properties_trigger(); + void null_properties_end(); + void null_properties_close(); + + void recent_files_load(); + void recent_files_write(); + void recent_files_clear(); + + void autosave_files_load(); + void autosave_files_open(); + void autosave_files_write(); + void autosave_files_clear(); + + std::filesystem::path autosave_directory_get(); + }; +} diff --git a/src/playback.cpp b/src/playback.cpp new file mode 100644 index 0000000..03c2117 --- /dev/null +++ b/src/playback.cpp @@ -0,0 +1,48 @@ +#include "playback.h" + +#include + +namespace anm2ed +{ + void Playback::toggle() + { + if (isFinished) time = 0.0f; + isFinished = false; + isPlaying = !isPlaying; + } + + void Playback::clamp(int length) + { + time = glm::clamp(time, 0.0f, (float)length - 1.0f); + } + + void Playback::tick(int fps, int length, bool isLoop) + { + if (isFinished) return; + + time += (float)fps / 30.0f; + + if (time >= (float)length) + { + if (isLoop) + time = 0.0f; + else + { + isPlaying = false; + isFinished = true; + } + } + } + + void Playback::decrement(int length) + { + --time; + clamp(length); + } + + void Playback::increment(int length) + { + ++time; + clamp(length); + } +} \ No newline at end of file diff --git a/src/playback.h b/src/playback.h new file mode 100644 index 0000000..ad4034c --- /dev/null +++ b/src/playback.h @@ -0,0 +1,18 @@ +#pragma once + +namespace anm2ed +{ + class Playback + { + public: + float time{}; + bool isPlaying{}; + bool isFinished{}; + + void toggle(); + void clamp(int); + void tick(int, int, bool); + void decrement(int); + void increment(int); + }; +} diff --git a/src/preview.cpp b/src/preview.cpp deleted file mode 100644 index 6ef404e..0000000 --- a/src/preview.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include "preview.h" - -static void _preview_render_textures_free(Preview* self) -{ - for (auto& texture : self->renderFrames) - texture_free(&texture); - - self->renderFrames.clear(); -} - -void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings) -{ - self->anm2 = anm2; - self->reference = reference; - self->resources = resources; - self->settings = settings; - - canvas_init(&self->canvas, vec2()); -} - -void preview_tick(Preview* self) -{ - f32& time = self->time; - Anm2Animation* animation = anm2_animation_from_reference(self->anm2, self->reference); - - if (animation) - { - if (self->isPlaying) - { - if (self->isRender) - { - ivec2& size = self->canvas.size; - u32 framebufferPixelCount = size.x * size.y * TEXTURE_CHANNELS; - std::vector framebufferPixels(framebufferPixelCount); - Texture frameTexture; - - glBindFramebuffer(GL_READ_FRAMEBUFFER, self->canvas.fbo); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, framebufferPixels.data()); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - texture_from_rgba_init(&frameTexture, size, framebufferPixels.data()); - self->renderFrames.push_back(frameTexture); - } - - time += (f32)self->anm2->fps / TICK_DELAY; - - if (time >= (f32)animation->frameNum - 1) - { - if (self->isRender) - { - self->isRender = false; - self->isRenderFinished = true; - time = 0.0f; - self->isPlaying = false; - } - else - { - if (self->settings->playbackIsLoop) - time = 0.0f; - else - { - time = std::clamp(time, 0.0f, std::max(0.0f, (f32)animation->frameNum - 1)); - self->isPlaying = false; - } - } - } - } - - if (self->settings->playbackIsClampPlayhead) - time = std::clamp(time, 0.0f, std::max(0.0f, (f32)animation->frameNum - 1)); - else - time = std::max(time, 0.0f); - } -} - -void preview_draw(Preview* self) -{ - ivec2& gridSize = self->settings->previewGridSize; - ivec2& gridOffset = self->settings->previewGridOffset; - vec4& gridColor = self->settings->previewGridColor; - GLuint& shaderLine = self->resources->shaders[SHADER_LINE]; - GLuint& shaderAxis = self->resources->shaders[SHADER_AXIS]; - GLuint& shaderTexture = self->resources->shaders[SHADER_TEXTURE]; - GLuint& shaderGrid = self->resources->shaders[SHADER_GRID]; - mat4 transform = canvas_transform_get(&self->canvas, self->settings->previewPan, self->settings->previewZoom, ORIGIN_CENTER); - - canvas_framebuffer_resize_check(&self->canvas); - - canvas_bind(&self->canvas); - canvas_viewport_set(&self->canvas); - canvas_clear(self->settings->previewBackgroundColor); - - if (self->settings->previewIsGrid) - canvas_grid_draw(&self->canvas, shaderGrid, transform, gridSize, gridOffset, gridColor); - - if (self->settings->previewIsAxes) - canvas_axes_draw(&self->canvas, shaderAxis, transform, self->settings->previewAxesColor); - - auto animation_draw = [&](s32 animationID) - { - Anm2Animation* animation = map_find(self->anm2->animations, animationID); - if (!animation) return; - - auto root_draw = [&](Anm2Frame root, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - mat4 model = quad_model_get(PREVIEW_TARGET_SIZE, root.position, PREVIEW_TARGET_SIZE * 0.5f, PERCENT_TO_UNIT(root.scale), root.rotation); - mat4 rootTransform = transform * model; - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_ROOT_COLOR; - AtlasType atlas = self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - f32 vertices[] = ATLAS_UV_VERTICES(atlas); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, rootTransform, vertices, color); - }; - - auto layer_draw = [&](mat4 rootModel, s32 id, f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Item& layerAnimation = animation->layerAnimations[id]; - if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0) return; - - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_LAYER, id}, time); - if (!frame.isVisible) return; - - mat4 model = quad_model_get(frame.size, frame.position, frame.pivot, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 layerTransform = transform * (rootModel * model); - vec3 frameColorOffset = frame.offsetRGB + colorOffset; - vec4 frameTint = frame.tintRGBA; - frameTint.a = std::max(0.0f, frameTint.a - alphaOffset); - - Anm2Spritesheet* spritesheet = map_find(self->anm2->spritesheets, self->anm2->layers[id].spritesheetID); - if (!spritesheet) return; - - Texture& texture = spritesheet->texture; - if (texture.isInvalid) return; - - vec2 inset = 0.5f / vec2(texture.size); - vec2 uvMin = frame.crop / vec2(texture.size) + inset; - vec2 uvMax = (frame.crop + frame.size) / vec2(texture.size) - inset; - f32 vertices[] = UV_VERTICES(uvMin, uvMax); - canvas_texture_draw(&self->canvas, shaderTexture, texture.id, layerTransform, vertices, frameTint, frameColorOffset); - - if (self->settings->previewIsBorder) - { - vec4 borderColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_BORDER_COLOR; - canvas_rect_draw(&self->canvas, shaderLine, layerTransform, borderColor); - } - - if (self->settings->previewIsPivots) - { - vec4 pivotColor = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : PREVIEW_PIVOT_COLOR; - f32 vertices[] = ATLAS_UV_VERTICES(ATLAS_PIVOT); - mat4 pivotModel = quad_model_get(CANVAS_PIVOT_SIZE, frame.position, CANVAS_PIVOT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 pivotTransform = transform * (rootModel * pivotModel); - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, pivotTransform, vertices, pivotColor); - } - }; - - auto null_draw = [&](mat4 rootModel, s32 id, f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Item& nullAnimation = animation->nullAnimations[id]; - if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0) return; - - Anm2Frame frame; - anm2_frame_from_time(self->anm2, &frame, Anm2Reference{animationID, ANM2_NULL, id}, time); - if (!frame.isVisible) return; - - Anm2Null null = self->anm2->nulls[id]; - - vec4 color = isOnionskin ? vec4(colorOffset, 1.0f - alphaOffset) : - (self->reference->itemType == ANM2_NULL && self->reference->itemID == id) ? - PREVIEW_NULL_SELECTED_COLOR : PREVIEW_NULL_COLOR; - - vec2 size = null.isShowRect ? CANVAS_PIVOT_SIZE : PREVIEW_TARGET_SIZE; - AtlasType atlas = null.isShowRect ? ATLAS_SQUARE : self->settings->previewIsAltIcons ? ATLAS_TARGET_ALT : ATLAS_TARGET; - - mat4 model = quad_model_get(size, frame.position, size * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 nullTransform = transform * (rootModel * model); - - f32 vertices[] = ATLAS_UV_VERTICES(atlas); - - canvas_texture_draw(&self->canvas, shaderTexture, self->resources->atlas.id, nullTransform, vertices, color); - - if (null.isShowRect) - { - mat4 rectModel = quad_model_get(PREVIEW_NULL_RECT_SIZE, frame.position, PREVIEW_NULL_RECT_SIZE * 0.5f, PERCENT_TO_UNIT(frame.scale), frame.rotation); - mat4 rectTransform = transform * (rootModel * rectModel); - canvas_rect_draw(&self->canvas, shaderLine, rectTransform, color); - } - }; - - auto base_draw = [&](f32 time, vec3 colorOffset = {}, f32 alphaOffset = {}, bool isOnionskin = {}) - { - Anm2Frame root; - anm2_frame_from_time(self->anm2, &root, Anm2Reference{animationID, ANM2_ROOT}, time); - - mat4 rootModel = self->settings->previewIsRootTransform ? - quad_model_parent_get(root.position, {}, PERCENT_TO_UNIT(root.scale), root.rotation) : mat4(1.0f); - - if (self->settings->previewIsIcons && animation->rootAnimation.isVisible && root.isVisible) - root_draw(root, colorOffset, alphaOffset, isOnionskin); - - for (auto id : animation->layerOrder) - layer_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - - if (self->settings->previewIsIcons) - for (auto& [id, _] : animation->nullAnimations) - null_draw(rootModel, id, time, colorOffset, alphaOffset, isOnionskin); - }; - - auto onionskin_draw = [&](s32 count, s32 direction, vec3 colorOffset) - { - for (s32 i = 1; i <= count; i++) - { - f32 time = self->time + (f32)(direction * i); - f32 alphaOffset = (1.0f / (count + 1)) * i; - base_draw(time, colorOffset, alphaOffset, true); - } - }; - - auto onionskins_draw = [&]() - { - if (!self->settings->onionskinIsEnabled) return; - onionskin_draw(self->settings->onionskinBeforeCount, -1, self->settings->onionskinBeforeColorOffset); - onionskin_draw(self->settings->onionskinAfterCount, 1, self->settings->onionskinAfterColorOffset); - }; - - if (self->settings->onionskinDrawOrder == ONIONSKIN_BELOW) onionskins_draw(); - base_draw(self->time); - if (self->settings->onionskinDrawOrder == ONIONSKIN_ABOVE) onionskins_draw(); - }; - - animation_draw(self->reference->animationID); - animation_draw(self->animationOverlayID); - - canvas_unbind(); -} - -void preview_render_start(Preview* self) -{ - self->isRender = true; - self->isPlaying = true; - self->time = 0.0f; - _preview_render_textures_free(self); - - self->normalCanvasSize = self->canvas.size; - self->normalCanvasPan = self->settings->previewPan; - self->normalCanvasZoom = self->settings->previewZoom; - - if (self->settings->renderIsUseAnimationBounds) - { - vec4 rect = anm2_animation_rect_get(self->anm2, self->reference, self->settings->previewIsRootTransform); - - self->canvas.size = ivec2 - ( - ceilf(rect.z * self->settings->renderScale), - ceilf(rect.w * self->settings->renderScale) - ); - - vec2 rectCenter = vec2(rect.x + rect.z * 0.5f, rect.y + rect.w * 0.5f); - self->settings->previewPan = -rectCenter * self->settings->renderScale; - self->settings->previewZoom = UNIT_TO_PERCENT(self->settings->renderScale); - } -} - -void preview_render_end(Preview* self) -{ - self->isRender = false; - self->isPlaying = false; - self->isRenderFinished = false; - _preview_render_textures_free(self); - - self->canvas.size = self->normalCanvasSize; - self->settings->previewPan = self->normalCanvasPan; - self->settings->previewZoom = self->normalCanvasZoom; -} - -void preview_free(Preview* self) -{ - canvas_free(&self->canvas); -} \ No newline at end of file diff --git a/src/preview.h b/src/preview.h deleted file mode 100644 index 7fcfa26..0000000 --- a/src/preview.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "anm2.h" -#include "resources.h" -#include "settings.h" -#include "canvas.h" - -const vec2 PREVIEW_SIZE = {2000, 2000}; -const vec2 PREVIEW_CANVAS_SIZE = {2000, 2000}; -const vec2 PREVIEW_CENTER = {0, 0}; - -#define PREVIEW_ZOOM_MIN 1 -#define PREVIEW_ZOOM_MAX 1000 -#define PREVIEW_ZOOM_STEP 25 -#define PREVIEW_GRID_MIN 1 -#define PREVIEW_GRID_MAX 1000 -#define PREVIEW_GRID_OFFSET_MIN 0 -#define PREVIEW_GRID_OFFSET_MAX 100 - -const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100}; -const vec2 PREVIEW_POINT_SIZE = {2, 2}; -const vec2 PREVIEW_TARGET_SIZE = {16, 16}; -const vec4 PREVIEW_BORDER_COLOR = COLOR_RED; -const vec4 PREVIEW_ROOT_COLOR = COLOR_GREEN; -const vec4 PREVIEW_NULL_COLOR = COLOR_BLUE; -const vec4 PREVIEW_NULL_SELECTED_COLOR = COLOR_RED; -const vec4 PREVIEW_PIVOT_COLOR = COLOR_RED; - -struct Preview -{ - Anm2* anm2 = nullptr; - Anm2Reference* reference = nullptr; - Resources* resources = nullptr; - Settings* settings = nullptr; - s32 animationOverlayID = ID_NONE; - Canvas canvas; - vec2 normalCanvasSize{}; - vec2 normalCanvasPan{}; - f32 normalCanvasZoom{}; - bool isPlaying = false; - bool isRender = false; - bool isRenderFinished = false; - bool isRenderCancelled = false; - std::vector renderFrames; - f32 time{}; -}; - -void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, Settings* settings); -void preview_draw(Preview* self); -void preview_tick(Preview* self); -void preview_free(Preview* self); -void preview_render_start(Preview* self); -void preview_render_end(Preview* self); \ No newline at end of file diff --git a/src/render.cpp b/src/render.cpp new file mode 100644 index 0000000..5d43203 --- /dev/null +++ b/src/render.cpp @@ -0,0 +1,145 @@ +#include "render.h" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include "util.h" + #define POPEN _popen + #define PCLOSE _pclose + #define PWRITE_MODE "wb" + #define PREAD_MODE "r" +#elif __unix__ + #define POPEN popen + #define PCLOSE pclose + #define PWRITE_MODE "w" + #define PREAD_MODE "r" +#endif + +#include "log.h" + +using namespace anm2ed::resource; +using namespace glm; + +namespace anm2ed +{ + constexpr auto FFMPEG_POPEN_ERROR = "popen() (for FFmpeg) failed!\n{}"; + + bool animation_render(const std::string& ffmpegPath, const std::string& path, std::vector& frames, + AudioStream& audioStream, render::Type type, ivec2 size, int fps) + { + if (frames.empty() || size.x <= 0 || size.y <= 0 || fps <= 0 || ffmpegPath.empty() || path.empty()) return false; + + std::filesystem::path audioPath{}; + std::string audioInputArguments{}; + std::string audioOutputArguments{"-an"}; + std::string command{}; + + auto remove_audio_file = [&]() + { + if (!audioPath.empty()) + { + std::error_code ec; + std::filesystem::remove(audioPath, ec); + } + }; + + if (type != render::GIF && !audioStream.stream.empty() && audioStream.spec.freq > 0 && + audioStream.spec.channels > 0) + { + audioPath = std::filesystem::temp_directory_path() / std::format("{}.f32", path); + + std::ofstream audioFile(audioPath, std::ios::binary); + + if (audioFile) + { + auto data = (const char*)audioStream.stream.data(); + auto byteCount = audioStream.stream.size() * sizeof(float); + audioFile.write(data, byteCount); + audioFile.close(); + + audioInputArguments = std::format("-f f32le -ar {0} -ac {1} -i \"{2}\"", audioStream.spec.freq, + audioStream.spec.channels, audioPath.string()); + + switch (type) + { + case render::WEBM: + audioOutputArguments = "-c:a libopus -b:a 160k -shortest"; + break; + case render::MP4: + audioOutputArguments = "-c:a aac -b:a 192k -shortest"; + break; + default: + break; + } + } + else + { + logger.warning("Failed to open temporary audio file; exporting video without audio."); + remove_audio_file(); + } + } + + command = std::format("\"{0}\" -y -f rawvideo -pix_fmt rgba -s {1}x{2} -r {3} -i pipe:0", ffmpegPath, size.x, + size.y, fps); + + if (!audioInputArguments.empty()) command += " " + audioInputArguments; + + switch (type) + { + case render::GIF: + command += + " -lavfi \"split[s0][s1];[s0]palettegen=stats_mode=full[p];[s1][p]paletteuse=dither=floyd_steinberg\"" + " -loop 0"; + command += std::format(" \"{}\"", path); + break; + case render::WEBM: + command += " -c:v libvpx-vp9 -crf 30 -b:v 0 -pix_fmt yuva420p -row-mt 1 -threads 0 -speed 2 -auto-alt-ref 0"; + if (!audioOutputArguments.empty()) command += " " + audioOutputArguments; + command += std::format(" \"{}\"", path); + break; + case render::MP4: + command += " -vf \"format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2\" -c:v libx265 -crf 20 -preset slow" + " -tag:v hvc1 -movflags +faststart"; + if (!audioOutputArguments.empty()) command += " " + audioOutputArguments; + command += std::format(" \"{}\"", path); + break; + default: + return false; + } + +#if _WIN32 + command = string::quote(command); +#endif + + logger.command(command); + + FILE* fp = POPEN(command.c_str(), PWRITE_MODE); + + if (!fp) + { + remove_audio_file(); + logger.error(std::format(FFMPEG_POPEN_ERROR, strerror(errno))); + return false; + } + + for (auto& frame : frames) + { + auto frameSize = frame.pixel_size_get(); + + if (fwrite(frame.pixels.data(), 1, frameSize, fp) != frameSize) + { + remove_audio_file(); + PCLOSE(fp); + return false; + } + } + + auto code = PCLOSE(fp); + remove_audio_file(); + return (code == 0); + } +} diff --git a/src/render.h b/src/render.h index 3cb8a87..22df9a7 100644 --- a/src/render.h +++ b/src/render.h @@ -1,28 +1,39 @@ #pragma once -#include "COMMON.h" +#include "audio_stream.h" +#include "texture.h" -enum RenderType +namespace anm2ed::render { - RENDER_PNG, - RENDER_GIF, - RENDER_WEBM, - RENDER_MP4, - RENDER_COUNT -}; +#define RENDER_LIST \ + X(PNGS, "PNGs", "") \ + X(GIF, "GIF", ".gif") \ + X(WEBM, "WebM", ".webm") \ + X(MP4, "MP4", ".mp4") -const inline std::string RENDER_TYPE_STRINGS[] = -{ - "PNG Images", - "GIF image", - "WebM video", - "MP4 video", -}; + enum Type + { +#define X(symbol, string, extension) symbol, + RENDER_LIST +#undef X + COUNT + }; -const inline std::string RENDER_EXTENSIONS[RENDER_COUNT] = + constexpr const char* STRINGS[] = { +#define X(symbol, string, extension) string, + RENDER_LIST +#undef X + }; + + constexpr const char* EXTENSIONS[] = { +#define X(symbol, string, extension) extension, + RENDER_LIST +#undef X + }; +} + +namespace anm2ed { - ".png", - ".gif", - ".webm", - ".mp4", -}; \ No newline at end of file + bool animation_render(const std::string&, const std::string&, std::vector&, AudioStream&, + render::Type, glm::ivec2, int); +} \ No newline at end of file diff --git a/src/resource/audio.cpp b/src/resource/audio.cpp new file mode 100644 index 0000000..af04685 --- /dev/null +++ b/src/resource/audio.cpp @@ -0,0 +1,54 @@ +#include "audio.h" + +#include + +namespace anm2ed::resource +{ + MIX_Mixer* Audio::mixer_get() + { + static MIX_Mixer* mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, nullptr); + return mixer; + } + + Audio::Audio(const char* path) + { + if (path && *path) internal = MIX_LoadAudio(mixer_get(), path, true); + } + + void Audio::unload() + { + if (!internal) return; + MIX_DestroyAudio(internal); + internal = nullptr; + } + + void Audio::play(MIX_Mixer* mixer) + { + MIX_PlayAudio(mixer ? mixer : mixer_get(), internal); + } + + Audio::Audio(Audio&& other) noexcept + { + internal = std::exchange(other.internal, nullptr); + } + + Audio& Audio::operator=(Audio&& other) noexcept + { + if (this != &other) + { + unload(); + internal = std::exchange(other.internal, nullptr); + } + return *this; + } + + Audio::~Audio() + { + unload(); + } + + bool Audio::is_valid() + { + return internal; + } +} diff --git a/src/resource/audio.h b/src/resource/audio.h new file mode 100644 index 0000000..569ae8a --- /dev/null +++ b/src/resource/audio.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace anm2ed::resource +{ + class Audio + { + MIX_Audio* internal{nullptr}; + MIX_Mixer* mixer_get(); + void unload(); + + public: + Audio(const char*); + ~Audio(); + Audio() = default; + Audio(Audio&&) noexcept; + Audio& operator=(Audio&&) noexcept; + Audio(const Audio&) = delete; + Audio& operator=(const Audio&) = delete; + + bool is_valid(); + void play(MIX_Mixer* = nullptr); + }; +} diff --git a/src/resource/audio_stream.cpp b/src/resource/audio_stream.cpp new file mode 100644 index 0000000..8c2c333 --- /dev/null +++ b/src/resource/audio_stream.cpp @@ -0,0 +1,26 @@ +#include "audio_stream.h" + +namespace anm2ed +{ + void AudioStream::callback(void* userData, MIX_Mixer* mixer, const SDL_AudioSpec* spec, float* pcm, int samples) + { + auto self = (AudioStream*)userData; + self->stream.insert(self->stream.end(), pcm, pcm + samples); + } + + AudioStream::AudioStream(MIX_Mixer* mixer) + { + MIX_GetMixerFormat(mixer, &spec); + } + + void AudioStream::capture_begin(MIX_Mixer* mixer) + { + MIX_SetPostMixCallback(mixer, callback, this); + } + + void AudioStream::capture_end(MIX_Mixer* mixer) + { + MIX_SetPostMixCallback(mixer, nullptr, this); + stream.clear(); + } +} \ No newline at end of file diff --git a/src/resource/audio_stream.h b/src/resource/audio_stream.h new file mode 100644 index 0000000..1cbb90f --- /dev/null +++ b/src/resource/audio_stream.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace anm2ed +{ + class AudioStream + { + static void callback(void*, MIX_Mixer*, const SDL_AudioSpec*, float*, int); + + public: + std::vector stream{}; + SDL_AudioSpec spec{}; + + AudioStream(MIX_Mixer*); + void capture_begin(MIX_Mixer*); + void capture_end(MIX_Mixer*); + }; +} \ No newline at end of file diff --git a/src/resource/font.cpp b/src/resource/font.cpp new file mode 100644 index 0000000..5504b19 --- /dev/null +++ b/src/resource/font.cpp @@ -0,0 +1,33 @@ +#include "font.h" + +namespace anm2ed::resource +{ + Font::Font() = default; + + Font::Font(void* data, size_t length, int size) + { + ImFontConfig config; + config.FontDataOwnedByAtlas = false; + pointer = ImGui::GetIO().Fonts->AddFontFromMemoryTTF(data, length, size, &config); + } + + Font::~Font() + { + if (get()) ImGui::GetIO().Fonts->RemoveFont(pointer); + } + + ImFont* Font::get() + { + return pointer; + } + + Font& Font::operator=(Font&& other) noexcept + { + if (this != &other) + { + pointer = other.pointer; + other.pointer = nullptr; + } + return *this; + } +} \ No newline at end of file diff --git a/src/resource/font.h b/src/resource/font.h new file mode 100644 index 0000000..a0708bb --- /dev/null +++ b/src/resource/font.h @@ -0,0 +1,5242 @@ +/* +Copyright 2018 The Noto Project Authors (github.com/noto-fonts/noto-fonts) + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +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 THE +COPYRIGHT HOLDER 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. +*/ + +#pragma once +#include +#include + +namespace anm2ed::resource::font +{ + constexpr auto SIZE = 16; + constexpr auto SIZE_LARGE = 32; + + enum Type + { + REGULAR, + ITALICS, + BOLD, + BOLD_ITALICS, + COUNT + }; + + struct Info + { + const void* data; + unsigned int length; + }; + + constexpr unsigned char REGULAR_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x05, 0xd0, 0x02, + 0xf1, 0x00, 0x00, 0x4f, 0xd8, 0x00, 0x00, 0x00, 0x56, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, + 0x50, 0x30, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, 0x00, 0x00, 0x57, 0xe4, 0x00, + 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x4f, 0x5e, 0x78, 0x00, 0x00, 0x3c, 0xe0, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3d, 0x40, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x3e, 0x0e, 0x1b, 0x37, 0x00, 0x00, 0x4c, 0x88, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x3d, 0x74, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x4f, 0xd0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xaf, 0xdf, 0xf8, 0x38, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x38, 0x4e, 0x68, 0x65, 0x61, 0x64, 0x28, 0x83, 0xdb, 0xfe, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0xb3, 0x0b, 0xe0, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xe7, 0xb3, 0x14, 0xa5, 0x00, 0x00, 0x3a, 0xd0, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, 0x0d, + 0xd0, 0xff, 0xd0, 0x00, 0x00, 0x39, 0x8c, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x75, + 0x00, 0x00, 0x39, 0x6c, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x6f, 0x43, 0x21, 0x00, 0x00, 0x4d, + 0xb4, 0x00, 0x00, 0x01, 0xfc, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, 0x00, 0x00, 0x4f, 0xb0, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4b, 0x80, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, + 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0xa3, 0x39, 0x19, 0x6b, 0x74, 0x24, 0x1a, 0x19, 0x25, 0x25, 0x19, 0x1a, 0x24, 0xc9, + 0x02, 0x01, 0xfd, 0x6c, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x41, 0x01, 0xc8, 0x01, 0x57, + 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, + 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xa0, 0x14, 0x37, 0x14, 0x01, + 0x16, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x19, + 0x00, 0x00, 0x02, 0x6c, 0x02, 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, + 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, + 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x23, 0x37, + 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, + 0x23, 0x01, 0xe0, 0x1f, 0x89, 0x96, 0x29, 0x47, 0x29, 0x8f, 0x27, 0x46, 0x26, 0x7e, 0x8b, 0x20, 0x86, 0x92, 0x28, + 0x48, 0x28, 0x90, 0x28, 0x45, 0x28, 0x7f, 0xfe, 0x7f, 0x8f, 0x1f, 0x8f, 0x01, 0xb4, 0xa0, 0x43, 0xd1, 0xd1, 0xd1, + 0xd1, 0x43, 0xa0, 0x42, 0xd4, 0xd4, 0xd4, 0xd4, 0x42, 0xa0, 0xa0, 0x00, 0x00, 0x03, 0x00, 0x3e, 0xff, 0xc6, 0x02, + 0x04, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x69, 0x40, 0x14, 0x30, 0x2a, 0x29, 0x23, 0x19, 0x18, + 0x15, 0x14, 0x08, 0x04, 0x0a, 0x01, 0x02, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x2d, 0x50, 0x58, + 0x40, 0x1c, 0x04, 0x01, 0x02, 0x03, 0x01, 0x03, 0x02, 0x01, 0x80, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, + 0x00, 0x05, 0x01, 0x00, 0x6a, 0x00, 0x03, 0x03, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x03, 0x02, 0x03, 0x85, + 0x04, 0x01, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x00, 0x05, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, + 0x01, 0x00, 0x62, 0x00, 0x00, 0x01, 0x00, 0x52, 0x59, 0x40, 0x09, 0x1f, 0x11, 0x11, 0x16, 0x15, 0x10, 0x06, 0x0d, + 0x1c, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x26, 0x26, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, + 0x15, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, + 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x37, 0x68, 0x20, 0x22, 0x6a, 0x33, + 0x63, 0x5c, 0x67, 0x58, 0x40, 0x35, 0x57, 0x24, 0x1b, 0x20, 0x4d, 0x28, 0x42, 0x58, 0x2d, 0x68, 0x5f, 0x40, 0x36, + 0x33, 0x2d, 0x3c, 0x40, 0x3b, 0x36, 0x30, 0x41, 0x31, 0x01, 0x11, 0x0f, 0x55, 0x10, 0x18, 0x01, 0xca, 0x1b, 0x52, + 0x47, 0x4a, 0x54, 0x05, 0x58, 0x57, 0x01, 0x15, 0x0f, 0x4a, 0x0d, 0x13, 0x03, 0xc9, 0x13, 0x2b, 0x3f, 0x32, 0x46, + 0x57, 0x0a, 0x6f, 0x02, 0x8c, 0x04, 0x2a, 0x21, 0x28, 0x2b, 0x0f, 0xfe, 0xe2, 0x06, 0x2b, 0x22, 0x26, 0x27, 0x10, + 0x00, 0x05, 0x00, 0x31, 0xff, 0xf6, 0x03, 0x0e, 0x02, 0xd4, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x25, 0x00, + 0x2f, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, + 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, + 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, + 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x05, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, + 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, 0x71, 0x07, 0x4e, 0x59, 0x40, 0x2b, 0x27, 0x26, + 0x1b, 0x1a, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2d, 0x2b, 0x26, 0x2f, 0x27, 0x2f, 0x21, 0x1f, 0x1a, 0x25, 0x1b, + 0x25, 0x17, 0x15, 0x10, 0x19, 0x11, 0x19, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, + 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, + 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0xc3, 0x4a, 0x4c, 0x49, 0x4d, + 0x47, 0x4b, 0x46, 0x02, 0x15, 0xfe, 0x74, 0x4d, 0x01, 0x8c, 0xfe, 0x84, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x01, 0x68, + 0x49, 0x4d, 0x49, 0x4d, 0x47, 0x4b, 0x46, 0x4c, 0x26, 0x23, 0x23, 0x26, 0x4d, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, + 0x77, 0x6a, 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x34, 0x51, 0x50, 0x50, 0x52, 0xa2, 0xa1, 0xe0, 0x75, 0x6a, + 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x3f, 0x50, 0x50, 0x51, 0x51, 0xa2, 0xa0, 0x00, 0x03, 0x00, 0x35, 0xff, 0xf6, + 0x02, 0xda, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x35, 0x00, 0x7a, 0x40, 0x0f, 0x26, 0x1a, 0x06, 0x03, 0x01, + 0x04, 0x35, 0x11, 0x0e, 0x07, 0x04, 0x05, 0x01, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, + 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, + 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x17, 0x21, 0x20, 0x01, 0x00, + 0x33, 0x31, 0x20, 0x2b, 0x21, 0x2b, 0x15, 0x13, 0x10, 0x0f, 0x0b, 0x0a, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x30, + 0x50, 0x5d, 0x51, 0x3e, 0xc1, 0x1a, 0x21, 0x0b, 0x59, 0x10, 0x30, 0x26, 0x92, 0x77, 0x57, 0x2f, 0x74, 0x53, 0x67, + 0x7a, 0x53, 0x47, 0x20, 0x37, 0x63, 0x52, 0x2a, 0x35, 0x26, 0x24, 0x3b, 0x33, 0x30, 0x52, 0x36, 0x3d, 0x4a, 0x3e, + 0x40, 0x5c, 0x1f, 0x02, 0xd5, 0x51, 0x49, 0x3f, 0x58, 0x24, 0xba, 0x1f, 0x51, 0x2f, 0x40, 0x6e, 0x29, 0x8e, 0x54, + 0x2a, 0x34, 0x66, 0x5e, 0x4d, 0x5d, 0x28, 0x24, 0x52, 0x37, 0x4a, 0x52, 0x48, 0x2c, 0x27, 0x24, 0x3d, 0x25, 0x22, + 0x3d, 0x28, 0x24, 0x2e, 0xfe, 0xc8, 0x20, 0x42, 0x36, 0x37, 0x42, 0x2a, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x41, 0x01, + 0xc8, 0x00, 0xa0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, + 0xa0, 0x14, 0x37, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x0e, + 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, + 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, + 0x26, 0x28, 0x47, 0x4c, 0x53, 0x46, 0x47, 0x47, 0x45, 0x52, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, + 0x77, 0x74, 0xdf, 0x5e, 0x58, 0xdf, 0x00, 0x00, 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x04, 0x02, 0xca, 0x00, 0x0d, + 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x01, 0x01, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, + 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x04, 0x47, + 0x4c, 0x52, 0x45, 0x47, 0x47, 0x46, 0x53, 0x4c, 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5e, 0xdf, 0x74, 0x77, 0xe2, + 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x29, 0x01, 0x36, 0x01, 0xfc, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x33, 0x40, 0x10, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x4b, 0xb0, 0x29, + 0x50, 0x58, 0xb6, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x1b, 0xb4, 0x01, 0x01, 0x00, 0x00, 0x76, 0x59, 0x40, + 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, + 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, 0x27, 0x01, 0x42, 0x14, 0xc0, 0x0e, 0xb8, 0x77, 0x56, 0x55, 0x4d, 0x59, 0x75, + 0xb6, 0x0e, 0xbe, 0x15, 0x02, 0xf8, 0xc0, 0x36, 0x5c, 0x0f, 0x9e, 0x2f, 0xaf, 0xaf, 0x2f, 0x9e, 0x0f, 0x5c, 0x36, + 0xc0, 0x00, 0x01, 0x00, 0x32, 0x00, 0x6f, 0x02, 0x08, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, + 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, + 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, + 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x41, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, + 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x29, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, + 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, + 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xc0, 0x0d, 0x31, 0x18, 0x41, + 0x0e, 0x1d, 0x07, 0x5e, 0x69, 0x35, 0x7f, 0x36, 0x39, 0x88, 0x34, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0xe5, 0x01, + 0x1a, 0x01, 0x33, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, + 0x35, 0x33, 0x15, 0x28, 0xf2, 0xe5, 0x4e, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x00, 0x79, + 0x00, 0x0b, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, + 0x02, 0x0d, 0x18, 0x2b, 0x37, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, + 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x36, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x01, 0x00, 0x0a, 0x00, + 0x00, 0x01, 0x6a, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, + 0x01, 0x6a, 0xfe, 0xf6, 0x56, 0x01, 0x0a, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x31, 0xff, 0xf6, + 0x02, 0x0b, 0x02, 0xd5, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, + 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x0b, 0x30, 0x68, 0x56, 0x79, 0x73, 0x2f, 0x68, + 0x55, 0x78, 0x76, 0xfe, 0x7e, 0x43, 0x51, 0x50, 0x45, 0x45, 0x50, 0x51, 0x43, 0x01, 0x66, 0x73, 0xa5, 0x58, 0xc3, + 0xad, 0x74, 0xa4, 0x57, 0xc1, 0xae, 0x93, 0x92, 0x91, 0x94, 0x92, 0x92, 0x92, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, + 0x01, 0x63, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, + 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x63, 0x56, 0x02, 0x02, 0x10, 0x1a, 0x14, 0x4c, + 0x2e, 0xc1, 0x49, 0x01, 0xf3, 0x2b, 0x34, 0x1c, 0x10, 0x16, 0x11, 0x3e, 0x3b, 0x96, 0x00, 0x00, 0x01, 0x00, 0x30, + 0x00, 0x00, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x2a, 0x40, 0x27, 0x0e, 0x0d, 0x02, 0x03, 0x01, 0x02, 0x01, + 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x27, 0x25, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, + 0x07, 0x15, 0x21, 0x02, 0x08, 0xfe, 0x28, 0xbb, 0x36, 0x4a, 0x26, 0x46, 0x38, 0x34, 0x4f, 0x29, 0x2f, 0x2a, 0x6d, + 0x44, 0x64, 0x74, 0x2e, 0x52, 0x37, 0x95, 0x01, 0x69, 0x49, 0xbd, 0x36, 0x54, 0x51, 0x30, 0x3b, 0x3d, 0x24, 0x20, + 0x3b, 0x23, 0x31, 0x65, 0x59, 0x38, 0x62, 0x5f, 0x36, 0x93, 0x04, 0x00, 0x00, 0x01, 0x00, 0x2d, 0xff, 0xf6, 0x02, + 0x03, 0x02, 0xd4, 0x00, 0x2a, 0x00, 0x40, 0x40, 0x3d, 0x24, 0x01, 0x03, 0x04, 0x03, 0x01, 0x02, 0x03, 0x0f, 0x01, + 0x01, 0x02, 0x0e, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x25, 0x01, 0x04, 0x01, 0x4b, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, + 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x25, 0x24, 0x21, 0x24, 0x25, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x15, + 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x01, 0xed, 0x50, 0x44, 0x56, 0x54, 0x3a, 0x79, 0x5f, 0x38, 0x60, 0x2c, 0x2d, 0x68, 0x30, 0x60, 0x55, 0x69, 0x5f, + 0x45, 0x46, 0x58, 0x5b, 0x46, 0x3c, 0x3a, 0x52, 0x28, 0x2c, 0x26, 0x71, 0x48, 0x70, 0x6d, 0x02, 0x23, 0x48, 0x55, + 0x0e, 0x04, 0x0a, 0x58, 0x47, 0x3e, 0x61, 0x36, 0x11, 0x16, 0x52, 0x16, 0x19, 0x4b, 0x42, 0x43, 0x3b, 0x4b, 0x4a, + 0x3d, 0x34, 0x39, 0x22, 0x1a, 0x3c, 0x1e, 0x2c, 0x64, 0x00, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, 0x02, 0x28, 0x02, + 0xce, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x2b, 0x40, 0x28, 0x0e, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, + 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x19, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, 0x35, + 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x03, 0x21, 0x02, 0x28, 0x68, 0x55, 0xfe, + 0xaa, 0x01, 0x50, 0x5b, 0x68, 0xbd, 0x04, 0x01, 0x04, 0x08, 0x18, 0x0b, 0xd6, 0x01, 0x00, 0xa2, 0xa2, 0xa2, 0x4b, + 0x01, 0xe1, 0xfe, 0x23, 0xe1, 0x34, 0x49, 0x21, 0x13, 0x2c, 0x0f, 0xfe, 0xcf, 0x00, 0x00, 0x01, 0x00, 0x3f, 0xff, + 0xf6, 0x02, 0x03, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0a, 0x02, + 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, 0x05, + 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, + 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x21, 0x07, 0x36, 0x36, 0x01, 0x13, 0x6e, 0x82, 0x8d, 0x7e, + 0x37, 0x61, 0x21, 0x24, 0x67, 0x2f, 0x4f, 0x61, 0x56, 0x5d, 0x1c, 0x48, 0x16, 0x2c, 0x1b, 0x01, 0x66, 0xfe, 0xe5, + 0x11, 0x11, 0x3a, 0x01, 0xb6, 0x6e, 0x64, 0x6f, 0x7f, 0x14, 0x13, 0x53, 0x16, 0x19, 0x4b, 0x4f, 0x46, 0x4b, 0x0a, + 0x05, 0x1c, 0x01, 0x51, 0x50, 0xcf, 0x03, 0x08, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, + 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x08, 0x01, 0x01, 0x00, 0x09, 0x01, 0x02, 0x01, 0x11, 0x01, 0x04, + 0x05, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, + 0x2c, 0x20, 0x2c, 0x24, 0x27, 0x25, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x15, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x26, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x37, 0x1b, 0x47, + 0x80, 0x65, 0x15, 0x33, 0x10, 0x12, 0x2d, 0x17, 0x45, 0x5c, 0x35, 0x18, 0x03, 0x06, 0x17, 0x52, 0x40, 0x5d, 0x72, + 0x7b, 0x68, 0x44, 0x6e, 0x41, 0xf2, 0x3f, 0x4e, 0x45, 0x45, 0x2f, 0x46, 0x27, 0x22, 0x44, 0x01, 0x31, 0x4d, 0x95, + 0x79, 0x48, 0x04, 0x05, 0x4b, 0x06, 0x06, 0x2e, 0x50, 0x68, 0x3b, 0x23, 0x31, 0x71, 0x68, 0x70, 0x80, 0x44, 0x8c, + 0x86, 0x51, 0x55, 0x44, 0x50, 0x27, 0x3c, 0x20, 0x2b, 0x55, 0x37, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x0b, + 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x5f, + 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, + 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x88, 0x01, 0x25, 0xfe, 0x7f, 0x01, 0xdf, + 0xfe, 0xde, 0x02, 0x7a, 0x50, 0x44, 0xfd, 0x7a, 0x00, 0x00, 0x03, 0x00, 0x31, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, + 0x00, 0x1b, 0x00, 0x28, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x23, 0x15, 0x07, 0x04, 0x03, 0x02, 0x01, 0x4c, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2d, 0x2b, 0x1c, 0x28, 0x1d, 0x28, 0x0f, 0x0d, 0x00, 0x1b, 0x01, + 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x27, 0x06, + 0x06, 0x01, 0x1d, 0x5e, 0x78, 0x25, 0x3e, 0x25, 0x2c, 0x48, 0x2b, 0x7f, 0x6b, 0x73, 0x7c, 0x29, 0x44, 0x27, 0x34, + 0x49, 0x38, 0x60, 0x3c, 0x37, 0x47, 0x23, 0x3c, 0x24, 0x34, 0x47, 0x46, 0xcf, 0x4a, 0x4d, 0x49, 0x4d, 0x52, 0x44, + 0x10, 0x42, 0x45, 0x02, 0xd4, 0x58, 0x53, 0x2b, 0x40, 0x31, 0x13, 0x15, 0x35, 0x46, 0x31, 0x5a, 0x69, 0x65, 0x5b, + 0x31, 0x48, 0x34, 0x12, 0x1e, 0x55, 0x42, 0x37, 0x4b, 0x28, 0x47, 0x35, 0x32, 0x25, 0x32, 0x23, 0x10, 0x16, 0x3e, + 0x36, 0x32, 0x35, 0xfe, 0x28, 0x34, 0x45, 0x45, 0x37, 0x34, 0x45, 0x1a, 0x06, 0x1c, 0x49, 0x00, 0x00, 0x02, 0x00, + 0x32, 0xff, 0xf6, 0x02, 0x08, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x05, 0x04, + 0x09, 0x01, 0x01, 0x02, 0x08, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x06, + 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x25, 0x27, 0x24, 0x24, 0x07, 0x0d, 0x1a, 0x2b, 0x01, + 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, + 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x27, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x02, 0x08, 0x1b, 0x47, 0x81, 0x65, 0x14, 0x35, 0x11, 0x27, 0x31, 0x46, 0x5b, 0x36, 0x18, + 0x02, 0x06, 0x16, 0x53, 0x41, 0x5c, 0x71, 0x39, 0x66, 0x45, 0x44, 0x6e, 0x40, 0xf2, 0x3e, 0x4f, 0x43, 0x46, 0x30, + 0x46, 0x27, 0x22, 0x44, 0x01, 0x99, 0x4d, 0x95, 0x79, 0x48, 0x05, 0x05, 0x4b, 0x0d, 0x2e, 0x4f, 0x69, 0x3a, 0x22, + 0x31, 0x71, 0x67, 0x4b, 0x6c, 0x3a, 0x45, 0x8b, 0x86, 0x52, 0x54, 0x45, 0x4f, 0x27, 0x3c, 0x20, 0x2b, 0x54, 0x38, + 0x00, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf2, 0x00, 0xc4, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, + 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x48, 0x24, 0x19, 0x1a, + 0x25, 0x25, 0x1a, 0x19, 0x24, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, + 0x24, 0x20, 0x20, 0xfe, 0x78, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x02, 0x00, 0x1f, 0xff, 0x7f, 0x00, + 0xc2, 0x02, 0x26, 0x00, 0x0b, 0x00, 0x15, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x02, 0x03, 0x02, 0x63, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x14, 0x15, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, 0x07, 0x23, 0x3e, 0x02, 0x37, + 0x33, 0x46, 0x24, 0x19, 0x1a, 0x25, 0x25, 0x1a, 0x19, 0x24, 0x71, 0x0d, 0x31, 0x18, 0x42, 0x0a, 0x13, 0x11, 0x05, + 0x5e, 0x01, 0xe2, 0x26, 0x1e, 0x1e, 0x26, 0x24, 0x20, 0x20, 0xfe, 0xab, 0x34, 0x81, 0x35, 0x26, 0x57, 0x55, 0x23, + 0x00, 0x01, 0x00, 0x32, 0x00, 0x74, 0x02, 0x09, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, + 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x09, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, + 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, 0x02, 0x00, 0x38, 0x00, 0xd9, 0x02, 0x02, 0x01, 0xe7, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, + 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, + 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, + 0x15, 0x38, 0x01, 0xca, 0xfe, 0x36, 0x01, 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, + 0x32, 0x00, 0x74, 0x02, 0x09, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, + 0x25, 0x35, 0x05, 0x15, 0x05, 0x32, 0x01, 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, + 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x0c, 0xff, 0xf2, 0x01, 0x98, 0x02, 0xd4, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x32, + 0x40, 0x2f, 0x0f, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, + 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, 0x00, 0x04, 0x04, + 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1b, 0x25, 0x2a, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x34, 0x36, 0x36, 0x37, 0x3e, 0x02, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, + 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8c, 0x0f, 0x25, + 0x20, 0x27, 0x2b, 0x12, 0x3e, 0x3b, 0x31, 0x4c, 0x23, 0x1f, 0x28, 0x61, 0x3c, 0x5f, 0x68, 0x1d, 0x35, 0x24, 0x21, + 0x23, 0x0c, 0x46, 0x17, 0x23, 0x1b, 0x19, 0x24, 0x24, 0x19, 0x1b, 0x23, 0xe4, 0x26, 0x37, 0x32, 0x1b, 0x21, 0x2c, + 0x2a, 0x1e, 0x30, 0x34, 0x19, 0x11, 0x46, 0x15, 0x1c, 0x5e, 0x51, 0x2d, 0x3f, 0x35, 0x1e, 0x1c, 0x2a, 0x29, 0x1d, + 0x11, 0x93, 0x25, 0x1e, 0x1e, 0x25, 0x24, 0x20, 0x20, 0x00, 0x00, 0x02, 0x00, 0x3a, 0xff, 0xa7, 0x03, 0x49, 0x02, + 0xca, 0x00, 0x3f, 0x00, 0x4d, 0x00, 0x7b, 0x40, 0x13, 0x16, 0x01, 0x09, 0x02, 0x47, 0x08, 0x02, 0x03, 0x09, 0x2f, + 0x01, 0x05, 0x00, 0x30, 0x01, 0x06, 0x05, 0x04, 0x4c, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, + 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, + 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, + 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, + 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, + 0x0e, 0x4b, 0x49, 0x25, 0x27, 0x25, 0x25, 0x26, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, + 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x49, 0x15, + 0x2c, 0x40, 0x2c, 0x2e, 0x35, 0x06, 0x05, 0x12, 0x46, 0x35, 0x4c, 0x53, 0x34, 0x5f, 0x41, 0x2c, 0x55, 0x18, 0x0a, + 0x01, 0x25, 0x19, 0x1f, 0x2b, 0x17, 0x4b, 0x83, 0x53, 0x72, 0x9d, 0x51, 0x9c, 0x93, 0x3d, 0x6f, 0x2b, 0x2b, 0x6b, + 0x41, 0x76, 0xa8, 0x59, 0x3a, 0x6e, 0x9d, 0x63, 0x68, 0xa2, 0x5d, 0xfe, 0x07, 0x33, 0x2b, 0x38, 0x31, 0x04, 0x06, + 0x0d, 0x28, 0x15, 0x31, 0x3c, 0x1a, 0x01, 0x65, 0x2e, 0x58, 0x47, 0x2b, 0x35, 0x22, 0x25, 0x32, 0x66, 0x54, 0x42, + 0x65, 0x3a, 0x0f, 0x09, 0xcb, 0x12, 0x0f, 0x03, 0x34, 0x22, 0x33, 0x55, 0x33, 0x5d, 0x81, 0x44, 0x5e, 0xa5, 0x6a, + 0x94, 0x9e, 0x1b, 0x10, 0x44, 0x12, 0x17, 0x58, 0xa5, 0x74, 0x5d, 0x9f, 0x75, 0x41, 0x56, 0xa0, 0xaf, 0x40, 0x3a, + 0x54, 0x43, 0x7d, 0x04, 0x06, 0x30, 0x4b, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x02, 0xcd, 0x00, + 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, + 0x00, 0x68, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x11, 0x10, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x21, 0x07, 0x23, 0x01, 0x33, 0x01, + 0x01, 0x2e, 0x02, 0x27, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x21, 0x56, 0xfe, 0xe5, 0x55, 0x5b, 0x01, 0x17, 0x51, + 0x01, 0x16, 0xfe, 0xe2, 0x03, 0x0e, 0x0d, 0x04, 0x07, 0x12, 0x06, 0x51, 0xe2, 0xdd, 0xdd, 0x02, 0xcd, 0xfd, 0x33, + 0x02, 0x05, 0x08, 0x2a, 0x2d, 0x0c, 0x1f, 0x3b, 0x11, 0xd8, 0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x02, 0x54, 0x02, + 0xca, 0x00, 0x10, 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, + 0x02, 0x08, 0x01, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x00, 0x04, 0x04, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, + 0x1a, 0x21, 0x1d, 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x23, 0x11, 0x13, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x15, 0x15, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x2d, 0x86, + 0x89, 0x46, 0x42, 0x2d, 0x49, 0x2a, 0x85, 0x73, 0xfb, 0xde, 0x5c, 0x44, 0x53, 0x5b, 0x76, 0x90, 0x5f, 0x4a, 0x4d, + 0x63, 0x02, 0xca, 0x4f, 0x62, 0x3f, 0x53, 0x0c, 0x05, 0x07, 0x26, 0x46, 0x38, 0x61, 0x6a, 0x02, 0xca, 0xfe, 0xd0, + 0x3b, 0x3a, 0x3b, 0x33, 0xe3, 0x4b, 0xfe, 0xfd, 0x4a, 0x3c, 0x38, 0x45, 0x00, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, + 0x02, 0x59, 0x02, 0xd4, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, + 0x0a, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, + 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x0e, 0x0c, 0x07, 0x05, 0x00, 0x1a, + 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x01, 0x93, 0x73, 0x84, 0x7b, + 0x7b, 0x2f, 0x54, 0x28, 0x28, 0x55, 0x3b, 0x6d, 0x92, 0x49, 0x4f, 0x9a, 0x6e, 0x71, 0x54, 0x24, 0x21, 0x51, 0x02, + 0x85, 0x9a, 0x86, 0x85, 0x9b, 0x10, 0x0c, 0x4e, 0x0f, 0x0e, 0x5a, 0xa6, 0x70, 0x6c, 0xa5, 0x5d, 0x2a, 0x4c, 0x0f, + 0x18, 0x00, 0x02, 0x00, 0x61, 0x00, 0x00, 0x02, 0x9d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x21, 0x25, 0x21, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, + 0x16, 0x07, 0x34, 0x26, 0x23, 0x23, 0x11, 0x33, 0x20, 0x02, 0x9d, 0xc5, 0xb0, 0xc7, 0xdc, 0x6c, 0x9e, 0x56, 0x5f, + 0x8d, 0x81, 0x75, 0x61, 0x01, 0x22, 0x01, 0x6c, 0xb5, 0xb7, 0x02, 0xca, 0x50, 0x9b, 0x76, 0x8f, 0x85, 0xfd, 0xd0, + 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf0, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, 0x40, 0x26, 0x00, 0x03, 0x00, + 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, + 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, + 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0x01, 0xf0, 0xfe, 0x71, 0x01, 0x8f, 0xfe, 0xcb, 0x01, + 0x23, 0xfe, 0xdd, 0x01, 0x35, 0x02, 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x00, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, + 0xf0, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, + 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, + 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, 0x21, 0x15, 0x21, 0x15, 0x21, 0x15, 0x21, 0xbb, 0x5a, 0x01, 0x8f, 0xfe, + 0xcb, 0x01, 0x22, 0xfe, 0xde, 0x02, 0xca, 0x4f, 0xfd, 0x4f, 0x00, 0x01, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0x8e, 0x02, + 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x10, 0x01, 0x03, 0x02, 0x11, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, + 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, + 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, 0x25, 0x25, + 0x26, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x35, 0x23, 0x01, 0x97, 0xf7, 0x3a, 0x76, 0x4b, 0x6f, 0x98, 0x4f, 0x58, 0xa5, 0x75, 0x3c, 0x6b, 0x2e, 0x22, 0x26, + 0x5f, 0x33, 0x80, 0x8f, 0x37, 0x76, 0x60, 0x2f, 0x42, 0x1b, 0x9d, 0x01, 0x79, 0xfe, 0xa2, 0x13, 0x12, 0x59, 0xa5, + 0x71, 0x70, 0xa4, 0x5b, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x9a, 0x86, 0x55, 0x83, 0x49, 0x0a, 0x07, 0xd4, 0x00, 0x00, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x83, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, + 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, + 0x33, 0x02, 0x83, 0x5a, 0xfe, 0x92, 0x5a, 0x5a, 0x01, 0x6e, 0x5a, 0x01, 0x4d, 0xfe, 0xb3, 0x02, 0xca, 0xfe, 0xd2, + 0x01, 0x2e, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x01, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, + 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, + 0x15, 0x07, 0x11, 0x17, 0x01, 0x2a, 0xfe, 0xfe, 0x54, 0x54, 0x01, 0x02, 0x54, 0x54, 0x34, 0x13, 0x02, 0x3b, 0x14, + 0x34, 0x34, 0x14, 0xfd, 0xc5, 0x13, 0x00, 0x00, 0x01, 0xff, 0xb2, 0xff, 0x42, 0x00, 0xb6, 0x02, 0xca, 0x00, 0x10, + 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, + 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x10, 0x01, 0x10, + 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, + 0x14, 0x06, 0x04, 0x18, 0x24, 0x0e, 0x10, 0x24, 0x14, 0x19, 0x2d, 0x1c, 0x5a, 0x66, 0xbe, 0x07, 0x06, 0x4c, 0x04, + 0x06, 0x14, 0x32, 0x2d, 0x02, 0xc6, 0xfd, 0x41, 0x67, 0x62, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x6b, 0x02, + 0xca, 0x00, 0x0e, 0x00, 0x20, 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, + 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, + 0x23, 0x03, 0x07, 0x11, 0x23, 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, 0x37, 0x33, 0x01, 0x02, 0x6b, 0x6a, 0xfd, 0x49, + 0x5a, 0x5a, 0x1e, 0x3e, 0x1f, 0xc1, 0x69, 0xfe, 0xe5, 0x01, 0x55, 0x40, 0xfe, 0xeb, 0x02, 0xca, 0xfe, 0xa0, 0x22, + 0x44, 0x22, 0xd8, 0xfe, 0xc9, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, + 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x61, + 0x5a, 0x01, 0x38, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x03, 0x2a, 0x02, 0xca, 0x00, + 0x15, 0x00, 0x27, 0x40, 0x24, 0x13, 0x0a, 0x01, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x15, 0x00, 0x15, 0x11, 0x13, 0x11, 0x16, + 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x16, 0x16, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, 0x11, + 0x23, 0x11, 0x34, 0x36, 0x37, 0x23, 0x03, 0x01, 0x9c, 0xeb, 0x04, 0x03, 0x04, 0x53, 0x85, 0xdc, 0x04, 0xe0, 0x84, + 0x59, 0x05, 0x02, 0x04, 0xee, 0x02, 0x72, 0x1f, 0x69, 0x39, 0xfe, 0x4f, 0x02, 0xca, 0xfd, 0xb7, 0x02, 0x49, 0xfd, + 0x36, 0x01, 0xb7, 0x34, 0x66, 0x20, 0xfd, 0x8f, 0x00, 0x01, 0x00, 0x61, 0x00, 0x00, 0x02, 0x97, 0x02, 0xca, 0x00, + 0x12, 0x00, 0x1d, 0x40, 0x1a, 0x02, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x17, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, + 0x15, 0x11, 0x23, 0x11, 0x33, 0x01, 0x33, 0x2e, 0x02, 0x35, 0x11, 0x33, 0x02, 0x97, 0x69, 0xfe, 0x82, 0x04, 0x02, + 0x06, 0x53, 0x68, 0x01, 0x7d, 0x04, 0x01, 0x03, 0x03, 0x54, 0x02, 0x51, 0x23, 0x68, 0x37, 0xfe, 0x71, 0x02, 0xca, + 0xfd, 0xb1, 0x10, 0x40, 0x4c, 0x20, 0x01, 0x93, 0x00, 0x00, 0x02, 0x00, 0x3d, 0xff, 0xf6, 0x02, 0xd0, 0x02, 0xd5, + 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, + 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, + 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xd0, 0x4b, 0x92, 0x6c, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, + 0x6b, 0x92, 0x4b, 0xfd, 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, + 0xa6, 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x02, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x02, + 0x04, 0x01, 0x67, 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, + 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, + 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x1e, 0x8c, 0x80, 0x35, 0x7d, 0x6b, 0x52, 0x5a, 0xb5, 0x5b, 0x48, + 0x66, 0x64, 0x58, 0x02, 0xca, 0x6e, 0x64, 0x3b, 0x67, 0x40, 0xfe, 0xea, 0x02, 0xca, 0x4d, 0xfe, 0xe6, 0x42, 0x4f, + 0x45, 0x44, 0x00, 0x02, 0x00, 0x3d, 0xff, 0x56, 0x02, 0xd0, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, + 0x28, 0x03, 0x01, 0x01, 0x03, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, + 0x05, 0x0d, 0x1b, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, + 0xd0, 0x69, 0x67, 0xab, 0x81, 0x8a, 0x06, 0x0d, 0x06, 0x6f, 0x93, 0x48, 0x48, 0x93, 0x70, 0x6b, 0x92, 0x4b, 0xfd, + 0xcc, 0x72, 0x79, 0x7a, 0x70, 0x70, 0x79, 0x79, 0x73, 0x01, 0x66, 0x83, 0xb8, 0x23, 0xb2, 0xa1, 0x01, 0x5c, 0xa6, + 0x6f, 0x6e, 0xa4, 0x5c, 0x5b, 0xa5, 0x6f, 0x87, 0x9b, 0x9b, 0x87, 0x87, 0x99, 0x99, 0x00, 0x00, 0x02, 0x00, 0x61, + 0x00, 0x00, 0x02, 0x5f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x3b, 0x40, 0x38, 0x07, 0x01, 0x02, 0x05, 0x01, + 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, + 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x10, 0x0f, 0x01, 0x00, 0x13, 0x11, 0x0f, 0x17, 0x10, 0x17, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x00, 0x0e, 0x01, 0x0e, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, 0x11, 0x17, 0x23, 0x11, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x01, 0x26, 0x85, 0x7f, 0x2a, 0x41, 0x24, 0xc4, 0x69, 0xad, 0x8e, 0x5a, 0xc0, 0x66, 0x6b, 0x57, 0x50, 0x54, 0x02, + 0xca, 0x65, 0x66, 0x39, 0x4c, 0x2d, 0x0d, 0xfe, 0xc0, 0x01, 0x27, 0xfe, 0xd9, 0x02, 0xca, 0x4e, 0xfe, 0xf7, 0x45, + 0x43, 0x46, 0x3b, 0x00, 0x01, 0x00, 0x33, 0xff, 0xf6, 0x01, 0xf6, 0x02, 0xd4, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, + 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, + 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xf6, 0x8a, 0x75, 0x3c, 0x66, 0x22, 0x24, 0x6b, 0x39, + 0x50, 0x51, 0x1e, 0x49, 0x41, 0x5b, 0x5d, 0x3a, 0x67, 0x43, 0x3b, 0x62, 0x28, 0x1c, 0x25, 0x57, 0x2f, 0x43, 0x44, + 0x1e, 0x44, 0x3a, 0x3f, 0x57, 0x2d, 0xbf, 0x5f, 0x6a, 0x12, 0x10, 0x56, 0x10, 0x1a, 0x3e, 0x35, 0x23, 0x30, 0x29, + 0x17, 0x21, 0x60, 0x53, 0x39, 0x51, 0x2c, 0x16, 0x12, 0x4d, 0x10, 0x16, 0x39, 0x2f, 0x24, 0x30, 0x26, 0x16, 0x17, + 0x35, 0x4a, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x21, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, 0x18, 0x03, + 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, + 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x43, 0x5a, 0xdf, 0x02, 0x17, + 0xde, 0x02, 0x7b, 0x4f, 0x4f, 0x00, 0x01, 0x00, 0x5a, 0xff, 0xf6, 0x02, 0x80, 0x02, 0xca, 0x00, 0x12, 0x00, 0x1b, + 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x80, 0x3c, 0x7b, 0x5f, 0x85, 0x8b, 0x5a, 0x5d, 0x5e, 0x61, + 0x57, 0x59, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x31, 0x57, 0x60, 0x67, 0x51, 0x01, 0xce, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x21, 0x40, 0x1e, 0x08, 0x01, 0x00, + 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x0c, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, + 0x36, 0x37, 0x13, 0x02, 0x58, 0xff, 0x5a, 0xff, 0x5e, 0xa1, 0x10, 0x16, 0x07, 0x07, 0x16, 0x10, 0xa0, 0x02, 0xca, + 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x36, 0x2c, 0x4d, 0x23, 0x23, 0x4e, 0x2d, 0x01, 0xc8, 0x00, 0x01, 0x00, 0x0c, 0x00, + 0x00, 0x03, 0x95, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x27, 0x40, 0x24, 0x1b, 0x12, 0x07, 0x03, 0x00, 0x02, 0x01, 0x4c, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x18, 0x11, 0x19, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x2e, 0x02, 0x27, 0x06, 0x06, + 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x36, + 0x36, 0x37, 0x13, 0x03, 0x95, 0xbe, 0x5b, 0x8b, 0x08, 0x10, 0x0a, 0x02, 0x01, 0x13, 0x0e, 0x87, 0x5b, 0xbd, 0x5e, + 0x6f, 0x0c, 0x11, 0x05, 0x05, 0x14, 0x0d, 0x7e, 0x5d, 0x83, 0x0e, 0x14, 0x05, 0x05, 0x12, 0x0c, 0x6e, 0x02, 0xca, + 0xfd, 0x36, 0x01, 0xd4, 0x1d, 0x3a, 0x2d, 0x09, 0x0d, 0x55, 0x2e, 0xfe, 0x2f, 0x02, 0xca, 0xfe, 0x4c, 0x2e, 0x56, + 0x26, 0x27, 0x5c, 0x2c, 0x01, 0xaf, 0xfe, 0x4e, 0x2e, 0x5b, 0x23, 0x25, 0x57, 0x2f, 0x01, 0xb3, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x00, 0x02, 0x46, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, 0x00, + 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, 0x12, + 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x03, 0x02, 0x46, + 0x66, 0xbd, 0xc0, 0x5f, 0xed, 0xde, 0x64, 0xaf, 0xb0, 0x5f, 0xdd, 0x01, 0x36, 0xfe, 0xca, 0x01, 0x74, 0x01, 0x56, + 0xfe, 0xe8, 0x01, 0x18, 0xfe, 0xac, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x36, 0x02, 0xca, 0x00, 0x08, + 0x00, 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, + 0x33, 0x01, 0x1b, 0xba, 0x61, 0xee, 0x5a, 0xee, 0x62, 0x01, 0x6b, 0x01, 0x5f, 0xfe, 0x4b, 0xfe, 0xeb, 0x01, 0x11, + 0x01, 0xb9, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x15, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, + 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, + 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, + 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x15, 0xfe, 0x11, 0x01, 0x78, 0xfe, 0x94, + 0x01, 0xd9, 0xfe, 0x88, 0x01, 0x82, 0x44, 0x02, 0x36, 0x50, 0x44, 0xfd, 0xca, 0x00, 0x01, 0x00, 0x50, 0xff, 0x62, + 0x01, 0x30, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, + 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, + 0x11, 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x30, 0xe0, 0xe0, 0x8a, 0x8a, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x00, + 0x01, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x6b, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, + 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, + 0x13, 0x01, 0x23, 0x01, 0x60, 0x01, 0x0b, 0x57, 0xfe, 0xf6, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x00, 0x01, + 0x00, 0x19, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x03, 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, + 0x1a, 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x8a, 0x8a, 0xe0, 0xe0, 0x56, 0x02, 0xd8, 0x48, + 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, + 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, + 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, + 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, + 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xfe, 0xff, 0x66, 0x01, 0xbe, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, + 0xb1, 0x06, 0x64, 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, + 0x01, 0x00, 0x4f, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0xbe, + 0xfe, 0x40, 0x01, 0xc0, 0x9a, 0x40, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x00, 0xf1, 0x02, 0xfe, 0x00, 0x0b, 0x00, + 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x0a, 0x04, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, + 0x85, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, + 0x44, 0x13, 0x1e, 0x02, 0x17, 0x15, 0x23, 0x2e, 0x02, 0x27, 0x35, 0x91, 0x0b, 0x21, 0x25, 0x0f, 0x3b, 0x17, 0x3a, + 0x31, 0x0c, 0x02, 0xfe, 0x16, 0x37, 0x34, 0x13, 0x0c, 0x12, 0x39, 0x39, 0x12, 0x0a, 0x00, 0x02, 0x00, 0x2e, 0xff, + 0xf6, 0x01, 0xe0, 0x02, 0x21, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, + 0x03, 0x04, 0x06, 0x01, 0x06, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, + 0x05, 0x06, 0x03, 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, + 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, + 0x05, 0x67, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, + 0x06, 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, + 0x1c, 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, + 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x35, 0x01, 0x20, 0x62, 0x5e, 0x40, 0x11, 0x04, 0x23, 0x4d, 0x44, 0x49, 0x60, 0x7e, 0x83, 0x5b, 0x3a, 0x35, + 0x2a, 0x4c, 0x21, 0x1b, 0x23, 0x60, 0x4e, 0x64, 0x4d, 0x37, 0x2b, 0x44, 0x5a, 0x02, 0x21, 0x56, 0x5e, 0xfe, 0x93, + 0x4c, 0x2c, 0x2a, 0x4d, 0x52, 0x50, 0x57, 0x04, 0x03, 0x20, 0x43, 0x34, 0x19, 0x10, 0x42, 0x13, 0x1b, 0xfe, 0xe2, + 0x04, 0x38, 0x33, 0x2d, 0x2a, 0x4b, 0x4e, 0x30, 0x00, 0x00, 0x02, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x30, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x21, 0x00, 0x8a, 0xb6, 0x10, 0x03, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x1c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x20, + 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, + 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x20, 0x06, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xad, 0x03, 0x02, 0x05, 0x17, 0x50, 0x3f, 0x64, 0x79, 0x7a, 0x63, 0x3f, + 0x50, 0x17, 0x07, 0x12, 0x3f, 0x58, 0x97, 0x55, 0x42, 0x41, 0x58, 0x48, 0x47, 0x02, 0x3f, 0x22, 0x3b, 0x11, 0x22, + 0x2e, 0x8b, 0x8a, 0x8a, 0x8c, 0x2e, 0x20, 0x44, 0x02, 0xf8, 0xfe, 0xe0, 0x62, 0x67, 0x04, 0x63, 0x69, 0x6a, 0x64, + 0xcb, 0x00, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x01, 0xbf, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x37, 0x40, 0x34, 0x0b, + 0x01, 0x02, 0x01, 0x17, 0x0c, 0x02, 0x03, 0x02, 0x18, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, + 0x15, 0x13, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0x01, 0x2c, 0x47, 0x6f, 0x3f, 0x42, 0x71, 0x48, 0x29, 0x4c, 0x18, 0x1b, 0x18, 0x40, 0x1c, 0x9e, + 0x4d, 0x4c, 0x2c, 0x43, 0x1c, 0x1b, 0x41, 0x0a, 0x3a, 0x7a, 0x5f, 0x63, 0x7c, 0x3a, 0x11, 0x0c, 0x49, 0x09, 0x10, + 0xcb, 0x61, 0x67, 0x12, 0x0d, 0x4e, 0x0e, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, + 0x00, 0x15, 0x00, 0x22, 0x00, 0x95, 0xb6, 0x12, 0x09, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, + 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, + 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x17, 0x16, + 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, + 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, + 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x01, 0x13, 0x64, 0x78, 0x79, 0x64, 0x3e, 0x4f, 0x19, 0x06, 0x01, 0x05, 0x58, 0x47, 0x0d, 0x04, 0x18, 0x50, 0x31, + 0x55, 0x45, 0x42, 0x59, 0x47, 0x47, 0x47, 0x0a, 0x8b, 0x8a, 0x8a, 0x8d, 0x2e, 0x21, 0x0d, 0x33, 0x0f, 0xd6, 0xfd, + 0x08, 0x48, 0x22, 0x30, 0x49, 0x5d, 0x5e, 0x10, 0x64, 0x6b, 0x71, 0x5f, 0x60, 0x6a, 0x00, 0x02, 0x00, 0x37, 0xff, + 0xf6, 0x02, 0x01, 0x02, 0x22, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x43, 0x40, 0x40, 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, + 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x19, 0x18, 0x01, + 0x00, 0x1c, 0x1b, 0x18, 0x1e, 0x19, 0x1e, 0x11, 0x0f, 0x0a, 0x08, 0x06, 0x05, 0x00, 0x17, 0x01, 0x17, 0x08, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x21, 0x26, 0x26, 0x01, 0x24, 0x45, 0x63, 0x35, + 0xfe, 0x91, 0x02, 0x59, 0x50, 0x33, 0x4f, 0x2a, 0x29, 0x50, 0x37, 0x4c, 0x75, 0x41, 0x3b, 0x6b, 0x46, 0x3f, 0x49, + 0x07, 0x01, 0x11, 0x01, 0x3e, 0x02, 0x22, 0x3c, 0x6d, 0x49, 0x35, 0x5b, 0x5f, 0x13, 0x12, 0x4d, 0x12, 0x11, 0x3e, + 0x7b, 0x59, 0x58, 0x7e, 0x44, 0x48, 0x51, 0x48, 0x44, 0x55, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x83, + 0x02, 0xfd, 0x00, 0x17, 0x00, 0x5c, 0x40, 0x0f, 0x0e, 0x01, 0x04, 0x03, 0x0f, 0x07, 0x02, 0x05, 0x04, 0x06, 0x01, + 0x00, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, + 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x1b, 0x40, 0x19, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, + 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x09, 0x13, 0x25, 0x25, 0x11, 0x11, 0x10, 0x06, + 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x4c, 0x87, 0x58, 0x5e, 0x5e, 0x5c, 0x52, 0x20, 0x35, 0x13, + 0x17, 0x10, 0x2a, 0x16, 0x2c, 0x2b, 0x87, 0x01, 0xd4, 0xfe, 0x2c, 0x01, 0xd4, 0x29, 0x1e, 0x1f, 0x68, 0x5b, 0x0b, + 0x07, 0x45, 0x05, 0x0a, 0x3b, 0x3f, 0x23, 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, + 0x1e, 0x00, 0x2b, 0x00, 0x80, 0x40, 0x0f, 0x16, 0x03, 0x02, 0x06, 0x05, 0x0d, 0x01, 0x03, 0x04, 0x0c, 0x01, 0x02, + 0x03, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, + 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, + 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x00, + 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x20, 0x1f, 0x01, 0x00, 0x26, 0x24, 0x1f, + 0x2b, 0x20, 0x2b, 0x1a, 0x18, 0x10, 0x0e, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x09, 0x0d, 0x16, 0x2b, + 0x01, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0x01, 0x13, 0x35, 0x55, 0x1e, 0x05, 0x0c, 0x46, 0x75, 0x7b, 0x76, 0x4b, 0x4f, + 0x77, 0x45, 0x4f, 0x02, 0x01, 0x04, 0x36, 0x70, 0x68, 0x75, 0x75, 0x73, 0x43, 0x4a, 0x49, 0x46, 0x51, 0x4a, 0x4c, + 0x02, 0x22, 0x28, 0x29, 0x47, 0xfd, 0xdf, 0x73, 0x74, 0x22, 0x51, 0x2a, 0x51, 0x46, 0x15, 0x0c, 0x2d, 0x09, 0x51, + 0x92, 0x83, 0x80, 0x97, 0x4a, 0x6b, 0x63, 0x63, 0x69, 0x57, 0x61, 0x15, 0x6e, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x02, 0x19, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x48, 0xb5, 0x02, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x4b, 0xb0, + 0x29, 0x50, 0x58, 0x40, 0x16, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, + 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x04, 0x04, 0x01, 0x5f, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0xb7, 0x11, 0x13, 0x22, + 0x13, 0x25, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, + 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xad, 0x05, 0x06, 0x1a, 0x59, 0x34, 0x62, 0x62, 0x57, 0x78, + 0x5a, 0x43, 0x58, 0x58, 0x02, 0x19, 0x28, 0x23, 0x29, 0x2a, 0x5d, 0x67, 0xfe, 0xa3, 0x01, 0x57, 0x81, 0x65, 0x5e, + 0xfe, 0xeb, 0x02, 0xf8, 0x00, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x00, 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x0f, + 0x00, 0x8d, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6c, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, + 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, + 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x6c, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, + 0x40, 0x15, 0x04, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x69, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x13, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, + 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x82, 0x14, 0x1f, 0x1f, 0x14, 0x16, 0x1e, 0x1e, 0x41, 0x58, 0x02, 0xe1, + 0x1b, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1b, 0xc9, 0xfd, 0xe8, 0x02, 0x18, 0x00, 0x02, 0xff, 0xc9, 0xff, 0x10, + 0x00, 0xb5, 0x02, 0xe1, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0xa5, 0x40, 0x0a, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, + 0x03, 0x02, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, + 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, + 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, + 0x50, 0x58, 0x40, 0x1b, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, + 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x19, 0x00, 0x00, 0x00, 0x01, + 0x04, 0x00, 0x01, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x6f, + 0x02, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x0f, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1b, 0x0d, 0x1b, 0x24, 0x22, + 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x4e, 0x1e, 0x16, 0x14, 0x1f, 0x1f, + 0x14, 0x16, 0x1e, 0x38, 0x19, 0x26, 0x0e, 0x0f, 0x20, 0x13, 0x20, 0x2a, 0x58, 0x48, 0x02, 0xa9, 0x1d, 0x1b, 0x1b, + 0x1d, 0x1c, 0x1c, 0x1c, 0xfc, 0x83, 0x07, 0x05, 0x47, 0x04, 0x06, 0x23, 0x31, 0x02, 0x6b, 0xfd, 0x98, 0x4b, 0x55, + 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x13, 0x00, 0x47, 0x40, 0x09, 0x0f, 0x0e, + 0x0b, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x11, 0x00, 0x03, 0x03, 0x6c, 0x4d, + 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x03, 0x03, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x59, 0xb6, 0x11, 0x13, 0x12, 0x19, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x37, + 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xac, 0x03, 0x01, 0x04, 0x06, 0x18, 0x19, 0x09, 0xab, + 0x67, 0xd9, 0xe8, 0x6a, 0xba, 0x3d, 0x57, 0x57, 0x01, 0x6b, 0x10, 0x34, 0x13, 0x08, 0x1e, 0x1f, 0x0a, 0xb5, 0xe5, + 0xfe, 0xcd, 0xfa, 0x35, 0xc5, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x00, 0xad, 0x02, 0xf8, 0x00, + 0x03, 0x00, 0x28, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x1b, 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x59, 0xb4, 0x11, + 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, 0x23, 0x11, 0x33, 0xad, 0x58, 0x58, 0x02, 0xf8, 0x00, 0x00, 0x01, 0x00, 0x55, + 0x00, 0x00, 0x03, 0x56, 0x02, 0x22, 0x00, 0x21, 0x00, 0x5d, 0xb6, 0x1e, 0x18, 0x02, 0x01, 0x02, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, + 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, + 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x59, 0x40, 0x17, 0x01, 0x00, 0x1d, 0x1b, 0x17, 0x16, 0x15, 0x14, 0x11, 0x0f, 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, + 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, + 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x17, 0x33, 0x36, 0x36, 0x02, 0xa1, 0x5b, 0x5a, 0x57, 0x6d, 0x4e, 0x43, 0x57, 0x6e, 0x51, 0x3e, 0x58, 0x47, 0x0d, + 0x05, 0x19, 0x55, 0x30, 0x7e, 0x26, 0x05, 0x1b, 0x5d, 0x02, 0x22, 0x5d, 0x68, 0xfe, 0xa3, 0x01, 0x59, 0x7f, 0x5a, + 0x56, 0xfe, 0xd8, 0x01, 0x59, 0x7f, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x5a, 0x2e, 0x2c, 0x00, + 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, 0x02, 0x19, 0x02, 0x22, 0x00, 0x13, 0x00, 0x50, 0xb5, 0x10, 0x01, 0x01, 0x02, + 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, + 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, + 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, + 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, 0x07, 0x05, 0x04, 0x00, 0x13, 0x01, 0x13, 0x06, 0x0d, 0x16, 0x2b, 0x01, + 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, + 0x01, 0x57, 0x60, 0x62, 0x57, 0x78, 0x59, 0x44, 0x58, 0x47, 0x0d, 0x05, 0x1a, 0x5c, 0x02, 0x22, 0x5d, 0x68, 0xfe, + 0xa3, 0x01, 0x57, 0x81, 0x64, 0x5e, 0xfe, 0xea, 0x02, 0x18, 0x49, 0x2a, 0x29, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, + 0x02, 0x27, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, 0x22, 0x04, + 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x27, 0x87, 0x73, 0x47, 0x6f, 0x40, 0x86, 0x73, + 0x49, 0x6f, 0x3f, 0xfe, 0x6b, 0x4b, 0x52, 0x51, 0x4c, 0x4c, 0x52, 0x52, 0x4a, 0x01, 0x0d, 0x85, 0x92, 0x41, 0x7d, + 0x59, 0x85, 0x90, 0x41, 0x7b, 0x59, 0x5f, 0x6f, 0x6f, 0x5f, 0x5f, 0x6c, 0x6c, 0x00, 0x02, 0x00, 0x55, 0xff, 0x10, + 0x02, 0x30, 0x02, 0x22, 0x00, 0x15, 0x00, 0x23, 0x00, 0x6b, 0xb6, 0x12, 0x09, 0x02, 0x05, 0x04, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, + 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x21, + 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, + 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, + 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x23, 0x17, 0x23, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, + 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, 0x15, 0x23, + 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x01, 0x54, 0x63, 0x79, 0x79, 0x64, 0x3e, 0x51, 0x17, 0x06, 0x02, 0x04, 0x58, 0x48, 0x0c, 0x04, 0x18, 0x4e, + 0x31, 0x52, 0x43, 0x02, 0x41, 0x58, 0x31, 0x3f, 0x1f, 0x47, 0x02, 0x22, 0x8a, 0x8b, 0x89, 0x8e, 0x2f, 0x1f, 0x11, + 0x34, 0x13, 0xdc, 0x03, 0x08, 0x49, 0x23, 0x30, 0x4a, 0x5c, 0x5e, 0x11, 0x63, 0x6b, 0x36, 0x5d, 0x3c, 0x5c, 0x6e, + 0x00, 0x00, 0x02, 0x00, 0x37, 0xff, 0x10, 0x02, 0x12, 0x02, 0x22, 0x00, 0x15, 0x00, 0x22, 0x00, 0x61, 0xb6, 0x10, + 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, + 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, + 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, + 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, + 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x37, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0xba, 0x02, + 0x03, 0x06, 0x17, 0x51, 0x40, 0x61, 0x79, 0x7b, 0x62, 0x3f, 0x50, 0x18, 0x04, 0x0d, 0x46, 0x58, 0x98, 0x53, 0x45, + 0x01, 0x44, 0x57, 0x48, 0x46, 0x47, 0x0b, 0x12, 0x30, 0x11, 0x22, 0x30, 0x8b, 0x8a, 0x8a, 0x8d, 0x30, 0x23, 0x49, + 0xfc, 0xf8, 0x01, 0x2f, 0x5b, 0x5e, 0x12, 0x66, 0x69, 0x71, 0x5f, 0x5f, 0x6b, 0x00, 0x01, 0x00, 0x55, 0x00, 0x00, + 0x01, 0x8e, 0x02, 0x22, 0x00, 0x13, 0x00, 0x66, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0b, 0x03, 0x01, 0x01, 0x00, + 0x10, 0x04, 0x02, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0b, 0x03, 0x01, 0x03, 0x00, 0x10, 0x04, 0x02, 0x02, 0x01, + 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, + 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, + 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x4f, 0x0f, + 0x23, 0x0d, 0x0b, 0x0d, 0x1f, 0x0e, 0x29, 0x48, 0x2b, 0x58, 0x48, 0x0a, 0x04, 0x1a, 0x52, 0x02, 0x22, 0x03, 0x03, + 0x51, 0x03, 0x04, 0x2d, 0x51, 0x36, 0xfe, 0xe2, 0x02, 0x18, 0x62, 0x2c, 0x40, 0x00, 0x00, 0x01, 0x00, 0x33, 0xff, + 0xf6, 0x01, 0xb2, 0x02, 0x22, 0x00, 0x29, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x07, 0x02, 0x01, + 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2c, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, + 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x02, 0x35, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, + 0x01, 0xb2, 0x74, 0x62, 0x38, 0x51, 0x1f, 0x20, 0x5b, 0x2f, 0x43, 0x3c, 0x16, 0x39, 0x35, 0x34, 0x4a, 0x28, 0x6f, + 0x5a, 0x31, 0x55, 0x25, 0x1e, 0x22, 0x4a, 0x27, 0x36, 0x39, 0x1a, 0x3d, 0x33, 0x33, 0x48, 0x26, 0x94, 0x4e, 0x50, + 0x12, 0x10, 0x50, 0x10, 0x1b, 0x2b, 0x24, 0x14, 0x20, 0x20, 0x14, 0x14, 0x28, 0x38, 0x2c, 0x44, 0x4a, 0x13, 0x11, + 0x46, 0x0e, 0x14, 0x23, 0x1e, 0x16, 0x1f, 0x1d, 0x14, 0x13, 0x28, 0x39, 0x00, 0x00, 0x01, 0x00, 0x10, 0xff, 0xf6, + 0x01, 0x53, 0x02, 0x93, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, 0x01, 0x00, 0x02, 0x04, + 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, + 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, 0x00, 0x15, 0x14, 0x13, + 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, 0x25, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, 0x33, 0x15, 0x23, 0x11, + 0x14, 0x16, 0x01, 0x08, 0x14, 0x2a, 0x0d, 0x0e, 0x34, 0x18, 0x2a, 0x47, 0x2c, 0x4c, 0x4d, 0x23, 0x34, 0x9b, 0x9b, + 0x2f, 0x3e, 0x07, 0x04, 0x43, 0x07, 0x09, 0x1d, 0x48, 0x41, 0x01, 0x38, 0x2a, 0x23, 0x72, 0x7b, 0x44, 0xfe, 0xca, + 0x31, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0x15, 0x02, 0x18, 0x00, 0x13, 0x00, 0x4c, 0xb5, 0x03, + 0x01, 0x03, 0x02, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6d, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x05, 0x04, 0x02, 0x02, + 0x02, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, + 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x22, 0x13, 0x24, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x11, + 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, 0x11, 0x14, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, + 0x15, 0x48, 0x0d, 0x04, 0x1a, 0x5c, 0x34, 0x61, 0x62, 0x59, 0x77, 0x59, 0x45, 0x02, 0x18, 0xfd, 0xe8, 0x47, 0x2a, + 0x27, 0x5d, 0x66, 0x01, 0x5f, 0xfe, 0xa7, 0x80, 0x64, 0x5e, 0x01, 0x17, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xfc, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, + 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, 0x0d, + 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x03, 0xcb, 0xcb, 0x5e, + 0x72, 0x08, 0x12, 0x0e, 0x03, 0x04, 0x04, 0x0f, 0x13, 0x07, 0x72, 0x5e, 0xcc, 0x02, 0x18, 0xfe, 0xc4, 0x16, 0x36, + 0x31, 0x11, 0x11, 0x32, 0x36, 0x15, 0x01, 0x3c, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x01, 0x03, 0x07, + 0x02, 0x19, 0x00, 0x22, 0x00, 0x21, 0x40, 0x1e, 0x1a, 0x0f, 0x03, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, + 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x19, 0x1a, 0x11, 0x18, 0x05, 0x0d, 0x1b, + 0x2b, 0x01, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x3e, + 0x02, 0x37, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x01, 0xaf, 0x0d, + 0x13, 0x05, 0x04, 0x04, 0x12, 0x0e, 0x60, 0x64, 0x93, 0x5b, 0x4a, 0x0b, 0x14, 0x04, 0x04, 0x04, 0x0b, 0x0e, 0x07, + 0x5f, 0x60, 0x5c, 0x0b, 0x15, 0x04, 0x04, 0x03, 0x15, 0x0c, 0x4b, 0x5a, 0x95, 0x67, 0x01, 0x2f, 0x29, 0x4f, 0x16, + 0x16, 0x4f, 0x2a, 0xfe, 0xd3, 0x02, 0x18, 0xfe, 0xe2, 0x2b, 0x58, 0x1d, 0x11, 0x32, 0x37, 0x16, 0x01, 0x2e, 0xfe, + 0xd2, 0x22, 0x50, 0x1d, 0x19, 0x58, 0x2e, 0x01, 0x1e, 0xfd, 0xe8, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, 0xff, + 0x02, 0x18, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, 0x2b, 0x13, + 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xd4, 0xb9, 0x64, 0x8a, 0x89, 0x63, 0xb9, 0xc3, + 0x64, 0x92, 0x94, 0x63, 0x01, 0x12, 0x01, 0x06, 0xca, 0xca, 0xfe, 0xfa, 0xfe, 0xee, 0xd6, 0xd6, 0x00, 0x00, 0x01, + 0x00, 0x01, 0xff, 0x10, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x1a, 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, 0x03, + 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, + 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x33, 0x13, 0x16, 0x16, 0x17, + 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x37, 0x01, 0x5e, 0x74, 0x0f, 0x18, 0x06, 0x04, 0x06, 0x1a, 0x0e, 0x6d, 0x5f, 0xe7, 0x1c, 0x59, 0x4e, 0x18, + 0x24, 0x0d, 0x0b, 0x1f, 0x11, 0x2e, 0x39, 0x10, 0x1c, 0x02, 0x18, 0xfe, 0xcf, 0x28, 0x49, 0x21, 0x19, 0x51, 0x29, + 0x01, 0x30, 0xfd, 0x9e, 0x4c, 0x5a, 0x05, 0x03, 0x46, 0x02, 0x04, 0x34, 0x2b, 0x47, 0x00, 0x01, 0x00, 0x27, 0x00, + 0x00, 0x01, 0xaf, 0x02, 0x18, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, + 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, + 0x15, 0x01, 0x21, 0x01, 0xaf, 0xfe, 0x78, 0x01, 0x20, 0xfe, 0xf1, 0x01, 0x70, 0xfe, 0xe4, 0x01, 0x23, 0x3a, 0x01, + 0x9a, 0x44, 0x42, 0xfe, 0x6e, 0x00, 0x01, 0x00, 0x1c, 0xff, 0x62, 0x01, 0x5c, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, + 0x40, 0x29, 0x16, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, + 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x15, 0x11, + 0x15, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x05, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x36, 0x36, 0x35, 0x35, + 0x34, 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x5c, + 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, 0x6e, 0x58, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x9e, 0x01, 0x4e, 0x50, 0x93, + 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x94, 0x50, 0x4e, 0x48, 0x01, 0x2c, 0x31, 0x90, 0x67, 0x13, 0x06, 0x13, 0x67, + 0x93, 0x31, 0x2b, 0x01, 0x00, 0x01, 0x00, 0xef, 0xff, 0x0f, 0x01, 0x38, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x28, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, + 0x0b, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, 0x18, + 0x2b, 0x13, 0x33, 0x11, 0x23, 0xef, 0x49, 0x49, 0x02, 0xf8, 0xfc, 0x17, 0x00, 0x00, 0x01, 0x00, 0x20, 0xff, 0x62, + 0x01, 0x60, 0x02, 0xca, 0x00, 0x1d, 0x00, 0x2c, 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x6a, 0x01, 0x4e, 0x15, 0x11, 0x15, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, 0x35, + 0x34, 0x37, 0x35, 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, 0x15, 0x06, + 0x06, 0x15, 0x15, 0x14, 0x06, 0x23, 0x20, 0x34, 0x3b, 0x6d, 0x6d, 0x3a, 0x35, 0x5c, 0x6a, 0x3f, 0x3b, 0x3b, 0x3f, + 0x6e, 0x58, 0x56, 0x02, 0x2b, 0x31, 0x91, 0x67, 0x13, 0x06, 0x13, 0x67, 0x92, 0x31, 0x2b, 0x01, 0x48, 0x01, 0x4e, + 0x50, 0x92, 0x33, 0x2b, 0x49, 0x01, 0x2a, 0x32, 0x95, 0x4f, 0x4f, 0x00, 0x00, 0x01, 0x00, 0x32, 0x01, 0x1f, 0x02, + 0x09, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, + 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, + 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, + 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x0d, 0x24, 0x2f, + 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, 0x31, 0x47, 0x1c, 0x3b, + 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, 0x36, 0x0d, 0x00, 0x01, + 0x00, 0x18, 0x01, 0xa0, 0x01, 0x33, 0x03, 0x55, 0x00, 0x19, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x01, 0x02, 0x0d, + 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, 0x02, 0x01, 0x69, 0x00, 0x03, + 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, 0x16, 0x25, 0x28, 0x10, 0x04, + 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x32, 0xfe, 0xe6, 0x73, 0x29, 0x29, 0x0f, 0x25, 0x1e, + 0x1e, 0x31, 0x1a, 0x23, 0x1d, 0x45, 0x2b, 0x40, 0x49, 0x3b, 0x38, 0x51, 0xc3, 0x01, 0xa0, 0x36, 0x70, 0x27, 0x31, + 0x27, 0x16, 0x20, 0x20, 0x17, 0x14, 0x2e, 0x19, 0x1e, 0x3f, 0x37, 0x31, 0x4e, 0x35, 0x4d, 0x00, 0x00, 0x01, 0x00, + 0x11, 0x01, 0x98, 0x01, 0x41, 0x03, 0x55, 0x00, 0x28, 0x00, 0x4d, 0x40, 0x4a, 0x26, 0x01, 0x05, 0x00, 0x25, 0x01, + 0x04, 0x05, 0x06, 0x01, 0x03, 0x04, 0x11, 0x01, 0x02, 0x03, 0x10, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, + 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, + 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x23, 0x21, 0x1d, 0x1b, 0x1a, 0x18, + 0x14, 0x12, 0x0e, 0x0c, 0x00, 0x28, 0x01, 0x28, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x23, 0x35, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xa5, 0x47, 0x48, 0x2b, + 0x1e, 0x27, 0x2f, 0x54, 0x59, 0x25, 0x40, 0x1e, 0x46, 0x3e, 0x34, 0x30, 0x3a, 0x34, 0x39, 0x39, 0x32, 0x2f, 0x29, + 0x1d, 0x1f, 0x35, 0x1b, 0x24, 0x1f, 0x45, 0x03, 0x55, 0x3e, 0x30, 0x28, 0x34, 0x0a, 0x03, 0x07, 0x33, 0x29, 0x3a, + 0x49, 0x0d, 0x0f, 0x3f, 0x22, 0x29, 0x23, 0x24, 0x21, 0x37, 0x27, 0x1f, 0x20, 0x1d, 0x15, 0x11, 0x2e, 0x17, 0x1a, + 0x00, 0x00, 0x01, 0x00, 0x25, 0x01, 0xa0, 0x00, 0xf0, 0x03, 0x4c, 0x00, 0x0c, 0x00, 0x27, 0x40, 0x24, 0x0b, 0x0a, + 0x06, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, + 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x13, 0x11, 0x23, + 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0xf0, 0x47, 0x03, 0x01, 0x0a, 0x18, 0x0d, 0x36, 0x23, + 0x82, 0x03, 0x4c, 0xfe, 0x54, 0x01, 0x14, 0x1a, 0x2a, 0x15, 0x09, 0x15, 0x09, 0x27, 0x31, 0x5c, 0x00, 0x00, 0x01, + 0xff, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, + 0x01, 0x23, 0x01, 0x01, 0x40, 0xfe, 0x4c, 0x4b, 0x01, 0xb4, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, + 0x0a, 0x01, 0xa0, 0x01, 0x55, 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x0e, 0x01, 0x04, 0x03, + 0x06, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x00, 0x03, 0x04, 0x01, 0x03, 0x57, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, + 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x01, 0x5f, 0x00, 0x01, 0x03, 0x01, 0x4f, 0x18, 0x11, 0x12, 0x11, 0x11, 0x10, + 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x37, + 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x55, 0x3d, 0x4b, 0xc3, 0xc5, 0x49, 0x3d, 0x88, 0x02, 0x01, 0x05, 0x20, 0x0b, + 0x50, 0x7d, 0x02, 0x00, 0x60, 0x60, 0x34, 0x01, 0x1b, 0xfe, 0xed, 0x5d, 0x15, 0x38, 0x18, 0x0b, 0x31, 0x11, 0x75, + 0x00, 0x00, 0x01, 0x00, 0x1e, 0x01, 0x97, 0x01, 0x40, 0x03, 0x4c, 0x00, 0x1e, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x03, + 0x02, 0x04, 0x01, 0x1c, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, + 0x01, 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, + 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x24, 0x25, 0x24, 0x23, + 0x11, 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x2b, + 0xb9, 0x09, 0x0c, 0x1d, 0x11, 0x43, 0x5a, 0x54, 0x52, 0x20, 0x46, 0x16, 0x1b, 0x45, 0x1a, 0x2d, 0x35, 0x35, 0x30, + 0x1a, 0x25, 0x0f, 0x1f, 0x10, 0x03, 0x4c, 0x37, 0x6d, 0x02, 0x04, 0x44, 0x40, 0x46, 0x4d, 0x0d, 0x0d, 0x43, 0x10, + 0x13, 0x28, 0x2b, 0x26, 0x2a, 0x08, 0x04, 0x14, 0xd0, 0x00, 0x01, 0x00, 0x1c, 0x01, 0xa0, 0x01, 0x43, 0x03, 0x4c, + 0x00, 0x06, 0x00, 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4f, 0xaa, 0xdd, 0x01, + 0x27, 0xaa, 0x01, 0xa0, 0x01, 0x70, 0x3c, 0x31, 0xfe, 0x85, 0x00, 0x00, 0x03, 0x00, 0x19, 0x01, 0x98, 0x01, 0x45, + 0x03, 0x54, 0x00, 0x18, 0x00, 0x24, 0x00, 0x31, 0x00, 0x38, 0x40, 0x35, 0x1f, 0x12, 0x06, 0x03, 0x03, 0x02, 0x01, + 0x4c, 0x04, 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x1a, 0x19, 0x01, 0x00, 0x2c, 0x2a, 0x19, 0x24, 0x1a, 0x24, 0x0d, + 0x0b, 0x00, 0x18, 0x01, 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x27, 0xb0, 0x37, 0x50, 0x2a, 0x1e, 0x27, 0x2f, 0x53, 0x42, 0x49, 0x4e, 0x2d, 0x20, 0x1f, 0x21, 0x26, 0x3f, + 0x24, 0x20, 0x24, 0x28, 0x1e, 0x1d, 0x25, 0x24, 0x2f, 0x21, 0x22, 0x28, 0x29, 0x2a, 0x28, 0x2d, 0x26, 0x03, 0x54, + 0x35, 0x37, 0x25, 0x30, 0x10, 0x10, 0x37, 0x29, 0x38, 0x43, 0x40, 0x38, 0x29, 0x36, 0x11, 0x14, 0x2b, 0x26, 0x24, + 0x31, 0x1a, 0x37, 0x1d, 0x1a, 0x1a, 0x22, 0x0c, 0x0b, 0x21, 0x1c, 0x1a, 0x1d, 0xb8, 0x10, 0x28, 0x1d, 0x1c, 0x24, + 0x24, 0x1c, 0x1d, 0x26, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x13, 0x01, 0x98, 0x01, 0x4a, 0x03, 0x54, 0x00, 0x0b, 0x00, + 0x15, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, + 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, 0x01, 0x00, 0x11, 0x0f, + 0x0c, 0x15, 0x0d, 0x15, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xae, 0x4d, + 0x4e, 0x4a, 0x51, 0x4d, 0x4f, 0x49, 0x53, 0x54, 0x54, 0x2b, 0x27, 0x27, 0x01, 0x98, 0x73, 0x6c, 0x6a, 0x73, 0x72, + 0x6b, 0x6a, 0x75, 0x3f, 0xa0, 0x9f, 0x4f, 0x51, 0x4f, 0x50, 0x00, 0x02, 0x00, 0x14, 0x01, 0x98, 0x01, 0x4c, 0x03, + 0x54, 0x00, 0x1c, 0x00, 0x29, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0b, 0x01, + 0x04, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, + 0x02, 0x04, 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, + 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, 0x29, 0x1e, 0x29, 0x16, 0x14, 0x10, 0x0e, 0x08, 0x06, 0x00, 0x1c, 0x01, + 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xec, 0x0e, 0x23, 0x0b, 0x0b, 0x22, 0x13, 0x36, 0x3e, 0x1b, 0x03, + 0x04, 0x0e, 0x36, 0x29, 0x3b, 0x4a, 0x52, 0x45, 0x44, 0x5d, 0x12, 0x2f, 0x54, 0x0d, 0x2b, 0x32, 0x14, 0x28, 0x1e, + 0x26, 0x2f, 0x29, 0x03, 0x54, 0x04, 0x03, 0x3b, 0x04, 0x05, 0x29, 0x46, 0x2a, 0x15, 0x1d, 0x46, 0x40, 0x46, 0x50, + 0x5f, 0x61, 0x2f, 0x5a, 0x48, 0x2b, 0xd7, 0x2d, 0x1a, 0x18, 0x2f, 0x1e, 0x2d, 0x2e, 0x26, 0x2b, 0x00, 0x02, 0x00, + 0x11, 0x01, 0x98, 0x01, 0x49, 0x03, 0x56, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x05, + 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, + 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, + 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x0f, + 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, + 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xa8, 0x44, 0x5d, 0x12, 0x2d, 0x54, 0x42, + 0x25, 0x1a, 0x0b, 0x20, 0x18, 0x37, 0x3c, 0x1b, 0x02, 0x05, 0x0d, 0x33, 0x28, 0x40, 0x4a, 0x52, 0x45, 0x24, 0x2f, + 0x27, 0x2a, 0x2b, 0x33, 0x2d, 0x03, 0x56, 0x5c, 0x63, 0x2f, 0x5b, 0x49, 0x2c, 0x07, 0x3c, 0x04, 0x06, 0x2c, 0x47, + 0x28, 0x13, 0x1f, 0x48, 0x40, 0x41, 0x53, 0x39, 0x2c, 0x2c, 0x26, 0x2e, 0x2d, 0x1a, 0x2a, 0x3b, 0xff, 0xff, 0x00, + 0x0f, 0x00, 0x00, 0x02, 0xdb, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, 0x58, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x4a, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x05, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x58, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, + 0x65, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x4a, 0x02, 0xb0, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x03, 0x5d, 0x02, 0xfd, 0x00, 0x26, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xb0, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x13, 0xff, 0xf8, 0x01, 0x4a, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, 0x00, + 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x18, 0x00, 0x00, 0x01, 0x33, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, + 0xf8, 0x01, 0x41, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x55, 0x01, 0xaf, 0x03, 0x07, 0x00, + 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x1e, 0xff, 0xf7, 0x01, 0x40, 0x01, 0xac, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, + 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf8, 0x01, 0x4c, 0x01, 0xb4, + 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x43, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0xff, 0xf8, 0x01, + 0x45, 0x01, 0xb4, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0xff, 0xf8, 0x01, 0x49, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x6a, 0x00, + 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x13, + 0x01, 0x16, 0x01, 0x4a, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, + 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x25, 0x01, 0x1e, 0x00, 0xf0, 0x02, 0xca, 0x03, 0x07, + 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x18, 0x01, 0x1e, 0x01, 0x33, 0x02, 0xd3, 0x03, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x41, 0x02, + 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x01, 0x1e, 0x01, 0x55, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, 0xff, + 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1e, 0x01, 0x15, + 0x01, 0x40, 0x02, 0xca, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, + 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x14, 0x01, 0x16, 0x01, 0x4c, 0x02, 0xd2, 0x03, 0x07, 0x00, 0x69, + 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x1c, 0x01, 0x1e, 0x01, 0x43, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x19, 0x01, 0x16, 0x01, 0x45, 0x02, 0xd2, 0x03, + 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x11, 0x01, 0x16, 0x01, 0x49, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, 0x00, + 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, + 0x01, 0x04, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, + 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, 0xa8, + 0x01, 0x27, 0x01, 0xbc, 0x02, 0x4b, 0x02, 0x66, 0x02, 0x8a, 0x02, 0xae, 0x02, 0xe6, 0x03, 0x0e, 0x03, 0x2e, 0x03, + 0x49, 0x03, 0x68, 0x03, 0x84, 0x03, 0xbd, 0x03, 0xe4, 0x04, 0x25, 0x04, 0x83, 0x04, 0xbe, 0x05, 0x11, 0x05, 0x71, + 0x05, 0x96, 0x06, 0x02, 0x06, 0x63, 0x06, 0x98, 0x06, 0xcb, 0x06, 0xe1, 0x07, 0x0c, 0x07, 0x22, 0x07, 0x7b, 0x08, + 0x25, 0x08, 0x5f, 0x08, 0xb6, 0x08, 0xfc, 0x09, 0x2b, 0x09, 0x57, 0x09, 0x7c, 0x09, 0xcc, 0x09, 0xf4, 0x0a, 0x1c, + 0x0a, 0x4d, 0x0a, 0x7a, 0x0a, 0x98, 0x0a, 0xd1, 0x0b, 0x01, 0x0b, 0x3d, 0x0b, 0x79, 0x0b, 0xc2, 0x0c, 0x08, 0x0c, + 0x5d, 0x0c, 0x7b, 0x0c, 0xa8, 0x0c, 0xd5, 0x0d, 0x22, 0x0d, 0x4d, 0x0d, 0x71, 0x0d, 0x9c, 0x0d, 0xbb, 0x0d, 0xd7, + 0x0d, 0xf6, 0x0e, 0x1d, 0x0e, 0x3a, 0x0e, 0x64, 0x0e, 0xdd, 0x0f, 0x55, 0x0f, 0x9b, 0x10, 0x19, 0x10, 0x6d, 0x10, + 0xc1, 0x11, 0x40, 0x11, 0x87, 0x11, 0xea, 0x12, 0x69, 0x12, 0xaf, 0x12, 0xcf, 0x13, 0x30, 0x13, 0x79, 0x13, 0xb2, + 0x14, 0x1e, 0x14, 0x83, 0x14, 0xd9, 0x15, 0x2e, 0x15, 0x75, 0x15, 0xbc, 0x15, 0xeb, 0x16, 0x37, 0x16, 0x60, 0x16, + 0xa1, 0x16, 0xcc, 0x17, 0x0e, 0x17, 0x2f, 0x17, 0x71, 0x17, 0xb6, 0x17, 0xf8, 0x18, 0x59, 0x18, 0x87, 0x18, 0xa3, + 0x18, 0xde, 0x19, 0x2e, 0x19, 0x55, 0x19, 0xbb, 0x19, 0xf6, 0x1a, 0x58, 0x1a, 0xb7, 0x1a, 0xc3, 0x1a, 0xcf, 0x1a, + 0xdb, 0x1a, 0xeb, 0x1a, 0xfb, 0x1b, 0x0a, 0x1b, 0x19, 0x1b, 0x28, 0x1b, 0x37, 0x1b, 0x46, 0x1b, 0x55, 0x1b, 0x64, + 0x1b, 0x73, 0x1b, 0x82, 0x1b, 0x91, 0x1b, 0xa0, 0x1b, 0xaf, 0x1b, 0xbe, 0x1b, 0xcd, 0x1b, 0xdc, 0x1b, 0xeb, 0x1b, + 0xfa, 0x1c, 0x09, 0x1c, 0x18, 0x1c, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xb1, 0xf9, + 0xad, 0x18, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, 0x00, + 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc0, 0xb7, 0xfd, 0x93, 0xfe, 0x7b, 0x0a, 0xf0, 0x04, 0x2b, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, 0x0d, 0x00, + 0x48, 0x01, 0x98, 0x00, 0x41, 0x02, 0x86, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x3e, 0x03, 0x3f, 0x00, 0x31, 0x02, 0xdc, + 0x00, 0x35, 0x00, 0xe1, 0x00, 0x41, 0x01, 0x2c, 0x00, 0x28, 0x01, 0x2c, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x29, 0x02, + 0x3c, 0x00, 0x32, 0x01, 0x0c, 0x00, 0x29, 0x01, 0x42, 0x00, 0x28, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x74, 0x00, 0x0a, + 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x59, 0x02, 0x3c, 0x00, 0x30, 0x02, 0x3c, 0x00, 0x2d, 0x02, 0x3c, 0x00, + 0x15, 0x02, 0x3c, 0x00, 0x3f, 0x02, 0x3c, 0x00, 0x37, 0x02, 0x3c, 0x00, 0x2c, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, + 0x00, 0x32, 0x01, 0x0c, 0x00, 0x48, 0x01, 0x0c, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x32, 0x02, 0x3c, 0x00, 0x38, 0x02, + 0x3c, 0x00, 0x32, 0x01, 0xb2, 0x00, 0x0c, 0x03, 0x83, 0x00, 0x3a, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x61, + 0x02, 0x78, 0x00, 0x3d, 0x02, 0xda, 0x00, 0x61, 0x02, 0x2c, 0x00, 0x61, 0x02, 0x07, 0x00, 0x61, 0x02, 0xd8, 0x00, + 0x3d, 0x02, 0xe5, 0x00, 0x61, 0x01, 0x53, 0x00, 0x28, 0x01, 0x11, 0xff, 0xb2, 0x02, 0x6b, 0x00, 0x61, 0x02, 0x0c, + 0x00, 0x61, 0x03, 0x8b, 0x00, 0x61, 0x02, 0xf8, 0x00, 0x61, 0x03, 0x0d, 0x00, 0x3d, 0x02, 0x5d, 0x00, 0x61, 0x03, + 0x0d, 0x00, 0x3d, 0x02, 0x6e, 0x00, 0x61, 0x02, 0x25, 0x00, 0x33, 0x02, 0x2c, 0x00, 0x0a, 0x02, 0xdb, 0x00, 0x5a, + 0x02, 0x58, 0x00, 0x00, 0x03, 0xa2, 0x00, 0x0c, 0x02, 0x4a, 0x00, 0x04, 0x02, 0x36, 0x00, 0x00, 0x02, 0x3c, 0x00, + 0x26, 0x01, 0x49, 0x00, 0x50, 0x01, 0x74, 0x00, 0x0a, 0x01, 0x49, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x26, 0x01, 0xbc, + 0xff, 0xfe, 0x01, 0x19, 0x00, 0x28, 0x02, 0x31, 0x00, 0x2e, 0x02, 0x67, 0x00, 0x55, 0x01, 0xe0, 0x00, 0x37, 0x02, + 0x67, 0x00, 0x37, 0x02, 0x34, 0x00, 0x37, 0x01, 0x58, 0x00, 0x0f, 0x02, 0x67, 0x00, 0x37, 0x02, 0x6a, 0x00, 0x55, + 0x01, 0x02, 0x00, 0x4e, 0x01, 0x02, 0xff, 0xc9, 0x02, 0x16, 0x00, 0x55, 0x01, 0x02, 0x00, 0x55, 0x03, 0xa7, 0x00, + 0x55, 0x02, 0x6a, 0x00, 0x55, 0x02, 0x5d, 0x00, 0x37, 0x02, 0x67, 0x00, 0x55, 0x02, 0x67, 0x00, 0x37, 0x01, 0x9d, + 0x00, 0x55, 0x01, 0xdf, 0x00, 0x33, 0x01, 0x69, 0x00, 0x10, 0x02, 0x6a, 0x00, 0x4f, 0x01, 0xfc, 0x00, 0x00, 0x03, + 0x12, 0x00, 0x0b, 0x02, 0x11, 0x00, 0x12, 0x01, 0xfe, 0x00, 0x01, 0x01, 0xd6, 0x00, 0x27, 0x01, 0x7c, 0x00, 0x1c, + 0x02, 0x27, 0x00, 0xef, 0x01, 0x7c, 0x00, 0x20, 0x02, 0x3c, 0x00, 0x32, 0x01, 0x5e, 0x00, 0x18, 0x01, 0x5e, 0x00, + 0x11, 0x01, 0x5e, 0x00, 0x25, 0x00, 0x82, 0xff, 0x41, 0x01, 0x5e, 0x00, 0x0a, 0x01, 0x5e, 0x00, 0x1e, 0x01, 0x5e, + 0x00, 0x1c, 0x01, 0x5e, 0x00, 0x19, 0x01, 0x5e, 0x00, 0x13, 0x01, 0x5e, 0x00, 0x14, 0x01, 0x5e, 0x00, 0x11, 0x02, + 0xb0, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x02, 0x5a, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, 0x03, 0xb2, 0x00, 0x0f, + 0x01, 0x5e, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, 0x00, + 0x19, 0x00, 0x11, 0x00, 0x13, 0x00, 0x25, 0x00, 0x18, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x19, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x18, 0xfd, + 0x93, 0xfd, 0x94, 0x0a, 0xf0, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x41, 0x01, 0x90, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0x00, + 0x00, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, + 0x05, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, + 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, + 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, + 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, + 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, + 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, + 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, + 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, + 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, + 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, + 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, + 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, + 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, + 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, + 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, + 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, + 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, + 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, + 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, + 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, + 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, + 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, + 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, + 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, + 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, + 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, + 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, + 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, + 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, + 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, + 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, + 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, + 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, + 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, + 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, + 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, + 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, + 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, + 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, + 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, + 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, + 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, + 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, + 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, + 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, + 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, + 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, + 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, + 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, + 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, + 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, + 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, + 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, + 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, + 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, + 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, + 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, + 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, + 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, + 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, + 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, + 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, + 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, + 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, + 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, + 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, + 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, + 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, + 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, + 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, + 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, + 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, + 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, + 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, + 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, + 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, + 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, + 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, + 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, + 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, + 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, + 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, + 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, + 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, + 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, + 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, + 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, + 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, + 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, + 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, + 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, + 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, + 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, + 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, + 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, + 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, + 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, + 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, + 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, + 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, + 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, + 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, + 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, + 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, + 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, + 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, + 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, + 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, + 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, + 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, + 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, + 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, + 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, + 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, + 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, + 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, + 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, + 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, + 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, + 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, + 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, + 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, + 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, + 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, + 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, + 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, + 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, + 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, + 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, + 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, + 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, + 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, + 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, + 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, + 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, + 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, + 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, + 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, + 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, + 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, + 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, + 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, + 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, + 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, + 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, + 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, + 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, + 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, + 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, + 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, + 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, + 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, + 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, + 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, + 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x51, + 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, + 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, 0x05, + 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, + 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, + 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, + 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, + 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, + 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, + 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, 0x0e, + 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x5d, 0x00, + 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0x22, + 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x00, 0x00, 0x02, 0x45, 0xff, + 0xf8, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4b, 0x00, 0x4b, 0x02, 0x3c, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x45, + 0x02, 0x45, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, + 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, + 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, + 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x48, 0x00, 0x48, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x5b, + 0x00, 0x5b, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, + 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, + 0x01, 0x2a, 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x32, 0xff, 0x76, 0x01, 0x61, 0x00, + 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x2c, 0x00, 0x2c, 0x02, 0xcb, 0x01, 0xa0, 0x02, 0xe0, + 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, + 0x0e, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x36, 0x00, 0xd6, 0x00, 0x03, 0x00, 0x01, + 0x04, 0x09, 0x00, 0x04, 0x00, 0x22, 0x01, 0x0c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, + 0x2e, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x20, 0x01, 0x82, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, + 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, + 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, + 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, + 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, + 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, + 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, + 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, + 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, + 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, + 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, + 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, + 0x2d, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x6f, + 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x52, 0x00, + 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, + 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, + 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, + 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, + 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, + 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, + 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, 0x00, + 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, + 0x00, 0x05, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x20, 0x00, 0x20, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, + 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x2d, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, + 0x01, 0x3b, 0x00, 0x01, 0x02, 0x77, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, + 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, + 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x6b, 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, + 0x07, 0x2c, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x15, 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, + 0x00, 0xa8, 0x00, 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, + 0xdc, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, + 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, + 0x3a, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, + 0xff, 0xc4, 0x00, 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, + 0x32, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, + 0x00, 0x0a, 0x00, 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, + 0xec, 0x00, 0x3e, 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, + 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, + 0x00, 0x08, 0x00, 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, + 0x28, 0x00, 0x02, 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, + 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xce, 0xff, 0xec, 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, + 0xff, 0xe2, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, + 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, + 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, + 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, + 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, + 0x00, 0x02, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, + 0x09, 0x00, 0x13, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x0f, 0x00, 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, + 0x03, 0x00, 0x26, 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, + 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, + 0x35, 0x00, 0x35, 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, + 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, + 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, + 0x00, 0x01, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, + 0x0d, 0x00, 0x57, 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, + 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, + 0x00, 0x07, 0x00, 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, + 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, + 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x04, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, + 0x00, 0x2a, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x32, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x01, 0x00, 0x06, 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, + 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, + 0x00, 0x7a, 0x00, 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, + 0x01, 0x00, 0x08, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, + 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, + 0x6d, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; + + constexpr unsigned char ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x09, 0x76, 0x04, + 0x22, 0x00, 0x00, 0x59, 0xdc, 0x00, 0x00, 0x00, 0x7a, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xa7, 0x00, 0x00, + 0x5a, 0x58, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, 0x00, 0x00, 0x61, 0xa8, 0x00, + 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x69, 0x50, 0x5f, 0x5f, 0x00, 0x00, 0x46, 0xec, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x47, 0x4c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x3d, 0xa5, 0x1a, 0xce, 0x00, 0x00, 0x56, 0x94, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x47, 0x80, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x59, 0xd4, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0x07, 0xce, 0x9d, 0x67, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x42, 0x36, 0x68, 0x65, 0x61, 0x64, 0x28, 0x38, 0xd8, 0x22, 0x00, 0x00, 0x44, 0x8c, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3b, 0x0b, 0x91, 0x00, 0x00, 0x46, 0xc8, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xec, 0x2d, 0x0f, 0x0b, 0x00, 0x00, 0x44, 0xc4, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, 0xd3, + 0x44, 0xc2, 0xf3, 0x00, 0x00, 0x43, 0x74, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x84, + 0x00, 0x00, 0x43, 0x54, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x5c, 0x42, 0x2a, 0x00, 0x00, 0x57, + 0xc0, 0x00, 0x00, 0x01, 0xf4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, 0x00, 0x00, 0x59, 0xb4, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x55, 0x8c, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x14, 0xff, 0xf2, 0x01, 0x13, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x2f, 0x40, 0x2c, 0x04, 0x01, + 0x01, 0x00, 0x03, 0x00, 0x01, 0x03, 0x80, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, + 0x02, 0x02, 0x71, 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x0e, 0x05, 0x0e, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x4d, 0x5b, 0x6b, 0x7f, 0x4b, 0x35, 0x24, 0x27, 0x17, 0x1c, 0x23, 0xc9, 0x02, 0x01, 0xfd, 0xff, 0xd7, 0x36, + 0x20, 0x31, 0x1c, 0x1a, 0x1d, 0x34, 0x00, 0x02, 0x00, 0x6d, 0x01, 0xc8, 0x01, 0x9c, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x01, + 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, + 0x2b, 0x01, 0x13, 0x33, 0x03, 0x23, 0x13, 0x33, 0x03, 0x01, 0x19, 0x23, 0x60, 0x4b, 0xe4, 0x23, 0x60, 0x4b, 0x01, + 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x8e, 0x02, + 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, + 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, + 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, + 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, + 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x61, 0x3b, 0x7e, 0x06, + 0x8b, 0x30, 0x86, 0x06, 0x92, 0x3c, 0x48, 0x3d, 0x90, 0x3e, 0x44, 0x3c, 0x80, 0x07, 0x8d, 0x2f, 0x8a, 0x06, 0x97, + 0x3c, 0x48, 0x3f, 0x90, 0x3d, 0x50, 0x90, 0x2d, 0x8f, 0xd1, 0x42, 0xa2, 0x41, 0xd4, 0xd4, 0xd4, 0xd4, 0x41, 0xa2, + 0x42, 0xd1, 0xd1, 0xd1, 0x01, 0x13, 0xa2, 0x00, 0x03, 0x00, 0x22, 0xff, 0xc6, 0x02, 0x0d, 0x02, 0xf6, 0x00, 0x23, + 0x00, 0x2a, 0x00, 0x31, 0x00, 0x82, 0x40, 0x14, 0x15, 0x12, 0x02, 0x03, 0x02, 0x31, 0x2a, 0x1a, 0x16, 0x08, 0x04, + 0x06, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x19, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x71, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, + 0x6c, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x31, 0x50, 0x58, 0x40, 0x18, 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x03, 0x03, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x03, 0x4e, 0x1b, 0x40, 0x1d, + 0x00, 0x04, 0x00, 0x04, 0x86, 0x00, 0x02, 0x00, 0x03, 0x01, 0x02, 0x03, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x01, 0x00, 0x51, 0x59, 0x59, 0xb7, 0x19, 0x17, 0x19, 0x15, 0x10, 0x05, + 0x0d, 0x1b, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, + 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xbe, 0x29, 0x54, 0x1f, + 0x27, 0x5c, 0x27, 0x2f, 0x3d, 0x47, 0x35, 0x5c, 0x39, 0x13, 0x41, 0x12, 0x26, 0x46, 0x1e, 0x21, 0x17, 0x3e, 0x23, + 0x2d, 0x44, 0x45, 0x38, 0x5e, 0x3b, 0x18, 0x41, 0x8c, 0x2f, 0x3b, 0x21, 0x22, 0x03, 0x2e, 0x40, 0x1f, 0x26, 0x32, + 0x02, 0x13, 0x0f, 0x50, 0x14, 0x17, 0x01, 0xd7, 0x17, 0x45, 0x3f, 0x39, 0x4c, 0x2b, 0x05, 0x55, 0x56, 0x03, 0x12, + 0x10, 0x47, 0x0d, 0x15, 0x02, 0xd1, 0x19, 0x43, 0x3b, 0x3a, 0x4f, 0x2d, 0x07, 0x6d, 0x02, 0x92, 0x05, 0x34, 0x31, + 0x19, 0x2a, 0x0d, 0xfe, 0xdf, 0x06, 0x37, 0x2f, 0x1a, 0x28, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x50, 0xff, 0xf6, 0x02, + 0xf3, 0x02, 0xd4, 0x00, 0x11, 0x00, 0x15, 0x00, 0x26, 0x00, 0x38, 0x00, 0x49, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, + 0x58, 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, + 0x00, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, + 0x0d, 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x04, 0x07, 0x09, + 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, + 0x0d, 0x01, 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x40, 0x2b, 0x3a, 0x39, 0x28, 0x27, 0x17, 0x16, 0x12, 0x12, 0x01, + 0x00, 0x43, 0x41, 0x39, 0x49, 0x3a, 0x49, 0x31, 0x2f, 0x27, 0x38, 0x28, 0x38, 0x20, 0x1e, 0x16, 0x26, 0x17, 0x26, + 0x12, 0x15, 0x12, 0x15, 0x14, 0x13, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, + 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x03, 0x01, 0x33, 0x01, 0x13, 0x32, 0x3e, 0x03, + 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0xc3, 0x37, + 0x3c, 0x0a, 0x19, 0x2b, 0x42, 0x2e, 0x39, 0x3c, 0x0b, 0x1a, 0x2d, 0x41, 0x7f, 0x02, 0x12, 0x4e, 0xfd, 0xee, 0x0b, + 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x1a, 0x0f, 0x07, 0x01, 0x9a, 0x37, 0x3c, 0x0a, 0x19, 0x2c, + 0x41, 0x2e, 0x3a, 0x3c, 0x0c, 0x1a, 0x2c, 0x42, 0x26, 0x1a, 0x27, 0x1a, 0x0f, 0x07, 0x1a, 0x19, 0x1a, 0x26, 0x19, + 0x0f, 0x07, 0x01, 0x14, 0x4b, 0x46, 0x1d, 0x4e, 0x52, 0x47, 0x2b, 0x47, 0x42, 0x1b, 0x4f, 0x55, 0x4a, 0x2e, 0xfe, + 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x56, 0x27, 0x3d, 0x42, 0x3a, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, + 0x50, 0xfe, 0xa0, 0x4a, 0x46, 0x1e, 0x4f, 0x52, 0x46, 0x2b, 0x47, 0x41, 0x1b, 0x4f, 0x55, 0x4b, 0x2e, 0x42, 0x27, + 0x3d, 0x43, 0x39, 0x0f, 0x29, 0x25, 0x24, 0x38, 0x41, 0x3c, 0x14, 0x50, 0x00, 0x00, 0x03, 0x00, 0x20, 0xff, 0xf6, + 0x02, 0x85, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x7b, 0x40, 0x0f, 0x32, 0x14, 0x06, 0x03, 0x02, + 0x04, 0x31, 0x1f, 0x1c, 0x15, 0x04, 0x05, 0x02, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, + 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, + 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, + 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, + 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x2f, 0x2e, 0x01, + 0x00, 0x2e, 0x38, 0x2f, 0x38, 0x2a, 0x28, 0x1e, 0x1d, 0x19, 0x18, 0x0e, 0x0c, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x13, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x03, 0x32, 0x36, 0x37, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, + 0xd8, 0x51, 0x67, 0x63, 0x5b, 0x13, 0x1e, 0x2d, 0x56, 0x3d, 0x49, 0x56, 0x35, 0x58, 0x35, 0x84, 0x21, 0x2e, 0x10, + 0x58, 0x19, 0x46, 0x2c, 0x63, 0x68, 0x37, 0x2f, 0x6a, 0x02, 0x20, 0x42, 0x2e, 0x28, 0x26, 0x31, 0x37, 0x18, 0x35, + 0x51, 0x25, 0x91, 0x24, 0x40, 0x28, 0x40, 0x0a, 0x5b, 0x57, 0x50, 0x69, 0x2b, 0x20, 0x4b, 0x2a, 0x33, 0x51, 0x30, + 0x4d, 0x42, 0x32, 0x48, 0x37, 0x1b, 0xb8, 0x1d, 0x4b, 0x28, 0x3d, 0x66, 0x2a, 0x85, 0x4e, 0x26, 0x32, 0x01, 0xbb, + 0x10, 0x27, 0x34, 0x23, 0x23, 0x2c, 0x3a, 0x33, 0x3b, 0xfe, 0x59, 0x2b, 0x1e, 0xce, 0x13, 0x2c, 0x3d, 0x2c, 0x33, + 0x3c, 0x00, 0x01, 0x00, 0x6d, 0x01, 0xc8, 0x00, 0xf0, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x6d, 0x23, 0x60, 0x4b, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x00, 0x01, + 0x00, 0x28, 0xff, 0x62, 0x01, 0x6f, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x00, 0x01, + 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, 0x2b, 0x17, + 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x70, 0x22, 0x26, 0x80, 0x76, 0x51, + 0x47, 0x6e, 0x3e, 0x1d, 0x1b, 0x9e, 0x3d, 0x94, 0x52, 0xb3, 0x01, 0x19, 0x79, 0x4e, 0xb5, 0xcd, 0x74, 0x57, 0x8f, + 0x3e, 0x00, 0x00, 0x01, 0xff, 0xb3, 0xff, 0x62, 0x00, 0xf9, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, + 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x17, 0x03, + 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, 0x02, 0x07, 0x4d, 0x47, + 0x6d, 0x3e, 0x1c, 0x1b, 0x44, 0x22, 0x25, 0x7f, 0x77, 0x9e, 0x4f, 0xb4, 0xce, 0x73, 0x56, 0x91, 0x3d, 0x3d, 0x94, + 0x53, 0xb2, 0xfe, 0xe7, 0x79, 0x00, 0x00, 0x01, 0x00, 0x67, 0x01, 0x2c, 0x02, 0x33, 0x02, 0xfb, 0x00, 0x0e, 0x00, + 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x05, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x04, 0x03, 0x02, 0x01, 0x07, + 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, 0x17, + 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x74, 0x36, 0x7b, 0x3d, 0x95, 0xb4, 0x1c, 0xb4, 0x14, 0x57, 0x3b, + 0xcc, 0x04, 0xbe, 0x57, 0x01, 0x2c, 0xc3, 0xa5, 0x3d, 0x89, 0x35, 0x4e, 0x59, 0xc1, 0x11, 0xba, 0x0a, 0x52, 0x17, + 0xb9, 0x00, 0x01, 0x00, 0x46, 0x00, 0x6f, 0x02, 0x1c, 0x02, 0x53, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, + 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, + 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, + 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x55, 0xc7, 0xc7, 0x48, 0xc7, 0xc7, 0x48, 0x01, 0x84, 0x47, + 0xce, 0xce, 0x47, 0xcf, 0x00, 0x00, 0x01, 0xff, 0xd5, 0xff, 0x7f, 0x00, 0x9c, 0x00, 0x74, 0x00, 0x08, 0x00, 0x17, + 0x40, 0x14, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, + 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x2b, 0x1a, 0x36, 0x13, 0x60, 0x04, + 0x19, 0x48, 0x23, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0xe3, 0x01, + 0x18, 0x01, 0x34, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, + 0x37, 0x33, 0x07, 0x1a, 0x12, 0xec, 0x12, 0xe3, 0x51, 0x51, 0x00, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf2, 0x00, 0x92, + 0x00, 0x79, 0x00, 0x0a, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x03, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x35, 0x34, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x48, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x0e, 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, + 0x33, 0x00, 0x01, 0xff, 0xd2, 0x00, 0x00, 0x01, 0xb9, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0x2e, 0x01, 0x8d, 0x5a, 0xfe, 0x74, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, + 0x00, 0x39, 0xff, 0xf6, 0x02, 0x16, 0x02, 0xd5, 0x00, 0x11, 0x00, 0x23, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x13, 0x12, 0x01, 0x00, 0x1c, 0x1a, 0x12, 0x23, 0x13, 0x23, 0x0a, 0x08, 0x00, 0x11, 0x01, 0x11, 0x06, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x03, 0x27, 0x32, 0x3e, + 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x03, 0x15, 0x14, 0x16, 0xec, 0x58, 0x5b, 0x14, 0x2b, 0x46, 0x63, 0x41, + 0x5c, 0x58, 0x16, 0x2d, 0x46, 0x62, 0x35, 0x28, 0x3f, 0x2f, 0x20, 0x10, 0x2f, 0x30, 0x26, 0x40, 0x31, 0x22, 0x12, + 0x30, 0x0a, 0x7e, 0x75, 0x3b, 0x86, 0x81, 0x6a, 0x40, 0x77, 0x6f, 0x48, 0x90, 0x82, 0x65, 0x3a, 0x4b, 0x34, 0x59, + 0x70, 0x79, 0x3a, 0x4a, 0x4f, 0x33, 0x57, 0x6c, 0x75, 0x36, 0x51, 0x57, 0x00, 0x00, 0x01, 0x00, 0x8f, 0x00, 0x00, + 0x01, 0xbc, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, + 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, + 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0x01, 0x29, 0x0a, 0x17, 0x09, 0x0f, 0x20, 0x14, 0x58, + 0x29, 0xe0, 0x4d, 0x99, 0x59, 0x01, 0xba, 0x2f, 0x60, 0x1d, 0x10, 0x18, 0x0d, 0x37, 0x42, 0x8e, 0xfd, 0x36, 0x00, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x0c, 0x02, + 0x02, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, + 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x27, 0x25, 0x28, 0x05, 0x0d, 0x19, + 0x2b, 0x33, 0x37, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x15, 0x21, 0x07, 0x03, 0x10, 0xe3, 0x42, 0x54, 0x28, 0x37, 0x33, 0x2c, 0x4a, + 0x23, 0x2a, 0x29, 0x64, 0x40, 0x5b, 0x61, 0x2c, 0x63, 0x53, 0xa8, 0x01, 0x46, 0x0f, 0x4b, 0xcd, 0x3c, 0x54, 0x4c, + 0x2f, 0x2d, 0x39, 0x24, 0x1a, 0x3c, 0x21, 0x2c, 0x5b, 0x48, 0x3a, 0x5f, 0x6a, 0x48, 0x92, 0x04, 0x50, 0x00, 0x00, + 0x01, 0x00, 0x16, 0xff, 0xf6, 0x02, 0x0d, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, + 0x1a, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, + 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, + 0x0c, 0x08, 0x06, 0x00, 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xd2, 0x3a, + 0x5b, 0x27, 0x23, 0x66, 0x34, 0x50, 0x56, 0x4b, 0x45, 0x40, 0x0f, 0x41, 0x32, 0x55, 0x33, 0x39, 0x2d, 0x2e, 0x4c, + 0x26, 0x29, 0x29, 0x65, 0x43, 0x5a, 0x5e, 0x62, 0x57, 0x39, 0x49, 0x36, 0x72, 0x0a, 0x15, 0x12, 0x55, 0x13, 0x1f, + 0x4d, 0x41, 0x3e, 0x40, 0x49, 0x23, 0x44, 0x2f, 0x2e, 0x31, 0x20, 0x1a, 0x3e, 0x1e, 0x28, 0x57, 0x47, 0x4c, 0x6a, + 0x10, 0x04, 0x0a, 0x4f, 0x41, 0x38, 0x65, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, + 0x00, 0x0a, 0x00, 0x16, 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, + 0x00, 0x04, 0x02, 0x00, 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, + 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x21, 0x37, 0x21, 0x37, 0x01, + 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x25, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x0e, 0x02, 0x07, 0x01, 0x20, 0x23, + 0xfe, 0xc3, 0x0f, 0x01, 0x93, 0x65, 0x63, 0x6e, 0x11, 0x6f, 0x23, 0xfe, 0xfa, 0xe5, 0x24, 0x08, 0x15, 0x15, 0x06, + 0x04, 0x08, 0x1a, 0x19, 0x09, 0xa2, 0x50, 0x01, 0xd8, 0xfe, 0x26, 0x4e, 0xa2, 0xf0, 0xab, 0x25, 0x51, 0x48, 0x17, + 0x0d, 0x24, 0x22, 0x0a, 0x00, 0x01, 0x00, 0x25, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xca, 0x00, 0x20, 0x00, 0x44, 0x40, + 0x41, 0x16, 0x11, 0x02, 0x02, 0x05, 0x10, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, + 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1a, 0x18, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, + 0x07, 0x05, 0x00, 0x20, 0x01, 0x20, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x02, 0xc8, 0x61, 0x42, 0x24, 0x53, 0x2c, 0x46, 0x56, 0x27, 0x48, 0x3e, 0x1e, 0x34, 0x20, 0x25, + 0x61, 0x01, 0x49, 0x11, 0xfd, 0x3c, 0x12, 0x2a, 0x1b, 0x59, 0x69, 0x1d, 0x41, 0x6f, 0x0a, 0x27, 0x55, 0x16, 0x1c, + 0x30, 0x4f, 0x2e, 0x3e, 0x44, 0x0a, 0x08, 0x1d, 0x01, 0x50, 0x50, 0xcf, 0x04, 0x06, 0x65, 0x58, 0x2d, 0x5b, 0x4c, + 0x2e, 0x00, 0x02, 0x00, 0x3f, 0xff, 0xf6, 0x02, 0x22, 0x02, 0xd4, 0x00, 0x1e, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, + 0x0c, 0x01, 0x02, 0x01, 0x0d, 0x01, 0x03, 0x02, 0x13, 0x01, 0x04, 0x05, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, + 0x03, 0x05, 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x01, 0x00, 0x27, 0x25, 0x1f, 0x30, 0x20, 0x30, 0x18, 0x16, + 0x11, 0x0f, 0x0b, 0x09, 0x00, 0x1e, 0x01, 0x1e, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x37, 0x36, 0x36, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x16, 0xfb, 0x54, 0x68, 0x20, 0x44, 0x35, 0x2b, 0x76, 0x4d, 0x36, 0x26, 0x12, 0x10, 0x29, 0x1b, 0x5f, + 0x91, 0x23, 0x04, 0x1d, 0x54, 0x34, 0x4a, 0x58, 0x1e, 0x3d, 0x5e, 0x37, 0x31, 0x44, 0x24, 0x34, 0x35, 0x24, 0x3c, + 0x29, 0x09, 0x07, 0x05, 0x16, 0x30, 0x0a, 0x6b, 0x70, 0x46, 0x9d, 0x91, 0x33, 0x2c, 0x30, 0x0b, 0x4c, 0x05, 0x07, + 0x84, 0x97, 0x26, 0x2d, 0x5e, 0x56, 0x32, 0x63, 0x51, 0x31, 0x4a, 0x38, 0x5b, 0x32, 0x38, 0x3d, 0x20, 0x2e, 0x15, + 0x10, 0x28, 0x14, 0x24, 0x3f, 0x28, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, 0x32, 0x02, 0xca, 0x00, 0x06, 0x00, + 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, + 0x01, 0x51, 0x01, 0x75, 0xfe, 0xa5, 0x10, 0x01, 0xb7, 0x0d, 0xfe, 0x8b, 0x02, 0x7c, 0x4e, 0x46, 0xfd, 0x7c, 0x00, + 0x00, 0x03, 0x00, 0x2d, 0xff, 0xf6, 0x02, 0x1f, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x36, 0x00, 0x35, 0x40, + 0x32, 0x30, 0x16, 0x07, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, + 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x36, + 0x2a, 0x36, 0x24, 0x22, 0x0f, 0x0d, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, + 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xf6, 0x45, 0x59, 0x2b, 0x64, 0x59, 0x26, 0x2f, + 0x38, 0x61, 0x3b, 0x42, 0x50, 0x24, 0x2f, 0x4c, 0x2c, 0x34, 0x3d, 0x33, 0x6c, 0x0f, 0x44, 0x47, 0x36, 0x2e, 0x35, + 0x41, 0x2c, 0x19, 0x32, 0x40, 0x1e, 0x32, 0x35, 0x2d, 0x49, 0x2a, 0x43, 0x0a, 0x31, 0x51, 0x31, 0x4d, 0x68, 0x22, + 0x1c, 0x46, 0x37, 0x3b, 0x54, 0x2d, 0x2d, 0x48, 0x29, 0x35, 0x49, 0x32, 0x13, 0x1f, 0x53, 0x41, 0x35, 0x5d, 0x39, + 0x01, 0xa6, 0x1a, 0x43, 0x35, 0x2b, 0x32, 0x3d, 0x35, 0x2d, 0x3a, 0xfe, 0x8d, 0x25, 0x3b, 0x20, 0x30, 0x48, 0x1c, + 0x0e, 0x29, 0x3f, 0x2f, 0x34, 0x3b, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x0a, 0x02, 0xd4, 0x00, 0x1f, + 0x00, 0x2e, 0x00, 0x47, 0x40, 0x44, 0x0a, 0x01, 0x04, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, + 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, + 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x29, 0x27, + 0x20, 0x2e, 0x21, 0x2e, 0x16, 0x14, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xa5, 0x1e, 0x3e, 0x1a, 0x1b, 0x3b, 0x22, 0x64, 0x77, 0x1e, 0x05, 0x19, + 0x4f, 0x30, 0x52, 0x5a, 0x3c, 0x70, 0x4d, 0x58, 0x62, 0x12, 0x22, 0x31, 0x20, 0x2e, 0x71, 0x2f, 0x2f, 0x4c, 0x15, + 0x0e, 0x36, 0x32, 0x32, 0x46, 0x25, 0x34, 0x0a, 0x09, 0x08, 0x51, 0x09, 0x0d, 0x8a, 0x8b, 0x23, 0x2b, 0x62, 0x5b, + 0x48, 0x7b, 0x4b, 0x6f, 0x6d, 0x34, 0x75, 0x73, 0x64, 0x23, 0x33, 0x2c, 0x01, 0x5a, 0x32, 0x2e, 0x22, 0x32, 0x3b, + 0x4b, 0x34, 0x57, 0x35, 0x3a, 0x40, 0x00, 0x02, 0x00, 0x14, 0xff, 0xf2, 0x00, 0xe1, 0x02, 0x26, 0x00, 0x0a, 0x00, + 0x15, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, + 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0c, 0x0b, 0x01, 0x00, 0x11, 0x0f, 0x0b, 0x15, 0x0c, 0x15, + 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x03, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x97, 0x34, 0x25, 0x28, 0x16, 0x1b, + 0x24, 0x75, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, 0x1f, 0x33, 0xfe, 0x53, + 0x34, 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0xff, 0xcf, 0xff, 0x7f, 0x00, 0xe1, 0x02, 0x26, 0x00, + 0x0a, 0x00, 0x13, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x80, 0x05, 0x01, 0x03, 0x03, + 0x84, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, 0x4e, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x13, + 0x0b, 0x13, 0x0f, 0x0e, 0x06, 0x04, 0x00, 0x0a, 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x35, 0x34, 0x36, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, 0x06, 0x07, 0x97, 0x34, 0x25, 0x28, + 0x16, 0x1b, 0x24, 0xee, 0x1a, 0x36, 0x13, 0x60, 0x04, 0x19, 0x48, 0x23, 0x01, 0x9f, 0x33, 0x22, 0x32, 0x1a, 0x1b, + 0x1f, 0x33, 0xfd, 0xe0, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, 0x37, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, 0x74, 0x02, + 0x1d, 0x02, 0x60, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, + 0x05, 0x02, 0x1d, 0xfe, 0x29, 0x01, 0xd7, 0xfe, 0x87, 0x01, 0x79, 0x74, 0xcf, 0x32, 0xeb, 0x4e, 0xb2, 0x9e, 0x00, + 0x02, 0x00, 0x4c, 0x00, 0xd9, 0x02, 0x16, 0x01, 0xe7, 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, + 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, + 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, + 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, 0x21, 0x15, 0x4c, 0x01, 0xca, 0xfe, 0x36, 0x01, + 0xca, 0x01, 0xa0, 0x47, 0x47, 0xc7, 0x47, 0x47, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00, 0x74, 0x02, 0x1d, 0x02, 0x60, + 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x46, 0x01, + 0x79, 0xfe, 0x87, 0x01, 0xd7, 0xfe, 0x29, 0xc2, 0x9d, 0xb3, 0x4e, 0xeb, 0x32, 0xcf, 0x00, 0x00, 0x02, 0x00, 0x4d, + 0xff, 0xf2, 0x01, 0xc6, 0x02, 0xd4, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x3f, 0x40, 0x3c, 0x0f, 0x01, 0x00, 0x01, 0x0e, + 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1e, 0x1d, + 0x00, 0x00, 0x23, 0x21, 0x1d, 0x27, 0x1e, 0x27, 0x00, 0x1c, 0x00, 0x1c, 0x25, 0x2a, 0x07, 0x0d, 0x18, 0x2b, 0x37, + 0x3e, 0x02, 0x37, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x07, + 0x1b, 0x2f, 0x24, 0x20, 0x37, 0x22, 0x30, 0x2e, 0x26, 0x49, 0x21, 0x20, 0x29, 0x62, 0x2f, 0x4f, 0x5e, 0x49, 0x46, + 0x27, 0x2b, 0x17, 0x08, 0x45, 0x34, 0x25, 0x28, 0x16, 0x1b, 0x24, 0xc9, 0x2b, 0x40, 0x37, 0x1c, 0x19, 0x2e, 0x38, + 0x26, 0x2c, 0x30, 0x19, 0x10, 0x43, 0x16, 0x1c, 0x4e, 0x4f, 0x43, 0x64, 0x34, 0x1c, 0x28, 0x2c, 0x23, 0xd7, 0x34, + 0x21, 0x32, 0x1b, 0x1a, 0x1f, 0x33, 0x00, 0x00, 0x02, 0x00, 0x35, 0xff, 0xa5, 0x03, 0x36, 0x02, 0xc9, 0x00, 0x40, + 0x00, 0x4e, 0x00, 0x90, 0x40, 0x13, 0x22, 0x01, 0x09, 0x04, 0x45, 0x14, 0x02, 0x05, 0x09, 0x3d, 0x01, 0x07, 0x02, + 0x3e, 0x01, 0x00, 0x07, 0x04, 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, + 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, + 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, + 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, + 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, 0x49, 0x47, 0x41, 0x4e, 0x42, 0x4e, 0x3b, 0x39, 0x33, 0x31, 0x2a, 0x28, 0x20, + 0x1e, 0x19, 0x17, 0x12, 0x10, 0x0a, 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, + 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x81, 0x65, 0x95, + 0x52, 0x40, 0x7a, 0xad, 0x6c, 0x6a, 0x85, 0x3f, 0x37, 0x60, 0x3e, 0x38, 0x2d, 0x04, 0x04, 0x16, 0x44, 0x32, 0x37, + 0x42, 0x45, 0x73, 0x44, 0x30, 0x40, 0x1a, 0x2f, 0x08, 0x08, 0x1c, 0x14, 0x1f, 0x32, 0x23, 0x13, 0x2f, 0x6a, 0x59, + 0x56, 0x8b, 0x64, 0x36, 0x88, 0x84, 0x36, 0x6c, 0x2c, 0x34, 0x70, 0x3c, 0x30, 0x3f, 0x13, 0x21, 0x0a, 0x1e, 0x14, + 0x2e, 0x4c, 0x2c, 0x20, 0x5b, 0x50, 0x97, 0x6a, 0x5b, 0xa8, 0x83, 0x4d, 0x53, 0x87, 0x50, 0x59, 0x8c, 0x50, 0x36, + 0x23, 0x25, 0x34, 0x49, 0x43, 0x51, 0x7b, 0x44, 0x12, 0x0b, 0xb3, 0x1e, 0x27, 0x11, 0x1f, 0x18, 0x2a, 0x45, 0x55, + 0x2b, 0x42, 0x6c, 0x41, 0x3d, 0x6d, 0x90, 0x53, 0x7f, 0x93, 0x19, 0x11, 0x41, 0x15, 0x17, 0x01, 0x04, 0x55, 0x43, + 0x7c, 0x04, 0x07, 0x36, 0x5c, 0x39, 0x2c, 0x28, 0x00, 0x02, 0xff, 0xc7, 0x00, 0x00, 0x02, 0x01, 0x02, 0xca, 0x00, + 0x07, 0x00, 0x11, 0x00, 0x2c, 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, + 0x02, 0x68, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, + 0x13, 0x33, 0x27, 0x26, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x39, 0x01, 0x84, 0x5e, 0x58, 0x58, 0x1b, 0xf1, 0x74, + 0x9f, 0xbd, 0x10, 0x04, 0x07, 0x01, 0x03, 0x10, 0x2a, 0x17, 0x02, 0xca, 0xfd, 0x36, 0xde, 0xde, 0x01, 0x2e, 0x96, + 0x26, 0x5c, 0x23, 0x26, 0x57, 0x2c, 0x00, 0x03, 0x00, 0x29, 0x00, 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x10, 0x00, + 0x1a, 0x00, 0x23, 0x00, 0x43, 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, + 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, + 0x06, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1c, 0x1b, 0x12, 0x11, 0x00, 0x00, 0x22, 0x20, 0x1b, 0x23, 0x1c, 0x23, + 0x19, 0x17, 0x11, 0x1a, 0x12, 0x1a, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xb9, 0x63, 0x71, 0x58, + 0x49, 0x31, 0x42, 0x47, 0x7b, 0x50, 0x41, 0x2d, 0x49, 0x2c, 0x3c, 0x46, 0x65, 0x30, 0x37, 0x55, 0x5c, 0x3e, 0x4a, + 0x70, 0x37, 0x02, 0xca, 0x4e, 0x56, 0x49, 0x5b, 0x0e, 0x05, 0x0d, 0x48, 0x3c, 0x49, 0x63, 0x32, 0x01, 0x9a, 0x1c, + 0x39, 0x2c, 0x2f, 0x33, 0xe3, 0xfe, 0xb2, 0x4c, 0x46, 0x30, 0x42, 0xfe, 0xfc, 0x00, 0x01, 0x00, 0x48, 0xff, 0xf6, + 0x02, 0x78, 0x02, 0xd4, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x1a, 0x0c, 0x02, 0x03, 0x02, + 0x1b, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, + 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x18, 0x16, 0x10, 0x0e, 0x0a, 0x08, 0x00, 0x1d, + 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x03, 0x33, 0x32, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x46, 0x77, 0x87, 0x1e, + 0x3d, 0x5d, 0x7c, 0x4e, 0x64, 0x4a, 0x24, 0x1b, 0x43, 0x2c, 0x4b, 0x6d, 0x48, 0x23, 0x5d, 0x52, 0x29, 0x4f, 0x26, + 0x27, 0x4f, 0x0a, 0x92, 0x7f, 0x40, 0x84, 0x76, 0x5d, 0x36, 0x28, 0x4a, 0x0e, 0x15, 0x43, 0x6f, 0x86, 0x44, 0x5b, + 0x69, 0x10, 0x0d, 0x4e, 0x0e, 0x10, 0x00, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x7c, 0x02, 0xca, 0x00, 0x09, + 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, + 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, + 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa9, 0x81, 0x92, 0x61, 0xbb, 0x87, + 0x05, 0x68, 0x8e, 0x4a, 0x69, 0x57, 0x55, 0x77, 0x02, 0xca, 0x8c, 0x91, 0x7c, 0xc2, 0x6f, 0x4d, 0x5e, 0xa0, 0x63, + 0x6e, 0x61, 0xfd, 0xd0, 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, + 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x33, 0x07, 0x21, 0x07, + 0x21, 0x07, 0x29, 0x97, 0x01, 0x6a, 0x11, 0xfe, 0xef, 0x2f, 0xff, 0x0f, 0xff, 0x00, 0x37, 0x01, 0x12, 0x11, 0x02, + 0xca, 0x4f, 0xdf, 0x4e, 0xff, 0x4f, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x02, 0xca, 0x00, 0x09, 0x00, + 0x29, 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x21, 0x07, 0x21, 0x07, 0x21, 0x03, 0x29, 0x97, 0x01, 0x6a, 0x10, + 0xfe, 0xee, 0x35, 0x01, 0x00, 0x11, 0xff, 0x00, 0x40, 0x02, 0xca, 0x4f, 0xfe, 0x4f, 0xfe, 0xd2, 0x00, 0x01, 0x00, + 0x48, 0xff, 0xf6, 0x02, 0x98, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, + 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1e, 0x1d, + 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, + 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x33, 0x03, 0x06, 0x06, 0x01, 0x57, 0x7f, 0x90, 0x37, 0x67, 0x8d, 0x56, + 0x41, 0x62, 0x2c, 0x22, 0x25, 0x56, 0x33, 0x52, 0x83, 0x4c, 0x27, 0x52, 0x40, 0x26, 0x3f, 0x16, 0x2e, 0x8c, 0x11, + 0xe5, 0x4c, 0x2d, 0x64, 0x0a, 0x8e, 0x7f, 0x62, 0xa9, 0x7f, 0x47, 0x16, 0x14, 0x4e, 0x11, 0x18, 0x62, 0xab, 0x6f, + 0x37, 0x59, 0x34, 0x0b, 0x07, 0xd3, 0x4e, 0xfe, 0xa3, 0x10, 0x15, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xac, + 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x68, 0x02, 0x01, 0x00, + 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x23, 0x13, 0x21, 0x03, + 0x2a, 0x97, 0x59, 0x40, 0x01, 0x3a, 0x40, 0x58, 0x97, 0x58, 0x46, 0xfe, 0xc6, 0x46, 0x02, 0xca, 0xfe, 0xd2, 0x01, + 0x2e, 0xfd, 0x36, 0x01, 0x4d, 0xfe, 0xb3, 0x00, 0x00, 0x01, 0xff, 0xec, 0x00, 0x00, 0x01, 0x7d, 0x02, 0xca, 0x00, + 0x0b, 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, + 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0x23, + 0x37, 0x37, 0x13, 0x27, 0x37, 0x33, 0x07, 0x07, 0x03, 0x17, 0x07, 0x14, 0x0a, 0x55, 0x7a, 0x4c, 0x0a, 0xfa, 0x0a, + 0x56, 0x7a, 0x4d, 0x0a, 0x31, 0x14, 0x02, 0x40, 0x13, 0x32, 0x32, 0x13, 0xfd, 0xc0, 0x14, 0x31, 0x00, 0x01, 0xff, + 0x64, 0xff, 0x42, 0x01, 0x1a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x28, 0x40, 0x25, 0x03, 0x01, 0x01, 0x02, 0x02, 0x01, + 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, 0x01, + 0x00, 0x0b, 0x0a, 0x07, 0x05, 0x00, 0x0e, 0x01, 0x0e, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x37, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x50, 0x32, 0x1a, 0x03, 0x0f, 0x24, 0x14, 0x2c, 0x44, 0x0d, + 0x96, 0x59, 0x97, 0x16, 0x6d, 0xbe, 0x0c, 0x4d, 0x04, 0x06, 0x38, 0x40, 0x02, 0xc1, 0xfd, 0x35, 0x65, 0x58, 0x00, + 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x02, 0x8b, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, + 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x37, 0x01, + 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x03, 0x29, 0x97, 0x59, 0x4a, 0x3e, 0x01, 0x12, 0x6c, 0xfe, 0xca, 0xa9, 0x62, + 0x8b, 0x53, 0x3c, 0x02, 0xca, 0xfe, 0xa5, 0x42, 0x01, 0x19, 0xfe, 0xc6, 0xfe, 0x70, 0x01, 0x5a, 0x3d, 0xfe, 0xe3, + 0x00, 0x00, 0x01, 0x00, 0x29, 0x00, 0x00, 0x01, 0xa4, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x21, 0x07, 0x29, 0x97, 0x59, 0x87, 0x01, + 0x12, 0x11, 0x02, 0xca, 0xfd, 0x86, 0x50, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x03, 0x4c, 0x02, 0xca, 0x00, + 0x16, 0x00, 0x27, 0x40, 0x24, 0x10, 0x0c, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x16, 0x11, 0x13, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, 0x13, 0x36, 0x36, 0x37, 0x23, 0x01, + 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x7e, 0x45, 0x04, 0x01, 0x3d, 0x89, 0x94, 0x5a, 0x5a, 0x0e, + 0x19, 0x09, 0x02, 0xfe, 0xa8, 0x47, 0x4c, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x5b, 0x02, 0xca, 0xfd, 0xb9, 0x02, 0x47, + 0xfd, 0x36, 0x01, 0xa8, 0x41, 0x6a, 0x20, 0xfd, 0x8d, 0x02, 0x72, 0x14, 0x43, 0x4b, 0x23, 0xfe, 0x53, 0x00, 0x00, + 0x01, 0x00, 0x28, 0x00, 0x00, 0x02, 0xc8, 0x02, 0xca, 0x00, 0x12, 0x00, 0x24, 0x40, 0x21, 0x0c, 0x03, 0x02, 0x02, + 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x12, 0x00, 0x12, 0x11, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x28, 0x97, 0x5f, 0xdb, 0x03, 0x05, 0x13, 0x0b, 0x54, + 0x55, 0x97, 0x5f, 0xdd, 0x03, 0x02, 0x0b, 0x0f, 0x08, 0x52, 0x02, 0xca, 0xfd, 0xb2, 0x24, 0x6f, 0x32, 0x01, 0x89, + 0xfd, 0x36, 0x02, 0x50, 0x15, 0x44, 0x4e, 0x25, 0xfe, 0x7c, 0x00, 0x02, 0x00, 0x48, 0xff, 0xf6, 0x02, 0xb2, 0x02, + 0xd5, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, + 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, + 0x02, 0x15, 0x14, 0x16, 0x01, 0x51, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x2d, 0x59, 0x84, 0x54, 0x3c, + 0x5e, 0x42, 0x23, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x0a, 0x95, 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, + 0x5d, 0xa4, 0x7d, 0x48, 0x4f, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, + 0x00, 0x29, 0x00, 0x00, 0x02, 0x37, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x30, 0x40, 0x2d, 0x06, 0x01, 0x03, + 0x00, 0x01, 0x02, 0x03, 0x01, 0x69, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, + 0x02, 0x6b, 0x02, 0x4e, 0x0c, 0x0b, 0x00, 0x00, 0x12, 0x10, 0x0b, 0x13, 0x0c, 0x13, 0x00, 0x0a, 0x00, 0x0a, 0x24, + 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x03, 0x13, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0xa1, 0x74, 0x62, 0xa0, 0x9a, 0x40, 0x3b, 0x89, 0x60, 0x71, 0x43, + 0x44, 0x4c, 0x3c, 0x02, 0xca, 0x67, 0x53, 0x79, 0x80, 0xfe, 0xe9, 0x01, 0x62, 0x53, 0x58, 0x3b, 0x35, 0xfe, 0xe5, + 0x00, 0x02, 0x00, 0x48, 0xff, 0x56, 0x02, 0xb2, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x24, 0x00, 0x32, 0x40, 0x2f, 0x12, + 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x24, + 0x16, 0x24, 0x17, 0x26, 0x22, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x06, 0x22, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x61, 0x04, 0x08, 0x04, 0x80, 0x89, 0x31, 0x5e, 0x86, 0x54, 0x7a, 0x87, 0x3a, + 0x6f, 0x50, 0x86, 0x72, 0x79, 0x3d, 0x5f, 0x41, 0x22, 0x5a, 0x4e, 0x3c, 0x60, 0x44, 0x24, 0x5c, 0x09, 0x01, 0x95, + 0x80, 0x5c, 0xa6, 0x7f, 0x49, 0x96, 0x83, 0x67, 0xb3, 0x80, 0x1b, 0xb1, 0xef, 0x3c, 0x69, 0x88, 0x4c, 0x5f, 0x69, + 0x3b, 0x67, 0x89, 0x4e, 0x5e, 0x6a, 0x00, 0x02, 0x00, 0x29, 0x00, 0x00, 0x02, 0x39, 0x02, 0xca, 0x00, 0x0c, 0x00, + 0x15, 0x00, 0x38, 0x40, 0x35, 0x07, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, + 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x0e, 0x0d, 0x00, 0x00, 0x14, 0x12, 0x0d, 0x15, 0x0e, 0x15, 0x00, 0x0c, 0x00, 0x0c, 0x11, 0x15, 0x21, 0x08, 0x0d, + 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x03, 0x13, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x23, 0x03, 0x29, 0x97, 0x9d, 0xdc, 0x51, 0x61, 0x76, 0x62, 0x66, 0x75, 0x3e, 0x9c, 0x64, 0x5b, + 0x44, 0x44, 0x4c, 0x39, 0x02, 0xca, 0xb5, 0x4d, 0x72, 0x1b, 0xfe, 0xc5, 0x01, 0x27, 0xfe, 0xd9, 0x01, 0x73, 0x57, + 0x45, 0x3d, 0x30, 0xfe, 0xf7, 0x00, 0x01, 0x00, 0x13, 0xff, 0xf6, 0x02, 0x07, 0x02, 0xd4, 0x00, 0x2a, 0x00, 0x37, + 0x40, 0x34, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x08, 0x06, 0x00, 0x2a, 0x01, 0x2a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x15, 0x14, + 0x06, 0xb9, 0x34, 0x4f, 0x23, 0x1e, 0x53, 0x36, 0x2d, 0x4c, 0x2e, 0x35, 0x41, 0x26, 0x3b, 0x21, 0x40, 0x6b, 0x40, + 0x38, 0x55, 0x26, 0x22, 0x1a, 0x4e, 0x29, 0x3d, 0x4f, 0x16, 0x2e, 0x22, 0x2b, 0x41, 0x25, 0x8f, 0x0a, 0x10, 0x10, + 0x58, 0x10, 0x1a, 0x1c, 0x3a, 0x2e, 0x28, 0x39, 0x25, 0x17, 0x31, 0x41, 0x2e, 0x42, 0x5d, 0x30, 0x16, 0x14, 0x4c, + 0x0e, 0x19, 0x40, 0x3a, 0x1e, 0x29, 0x21, 0x15, 0x1a, 0x32, 0x42, 0x31, 0x6b, 0x6e, 0x00, 0x01, 0x00, 0x5a, 0x00, + 0x00, 0x02, 0x4d, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, + 0x01, 0x6a, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, + 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x98, 0x86, 0xc4, 0x11, 0x01, 0xe2, 0x10, + 0xc4, 0x87, 0x02, 0x7b, 0x4f, 0x4f, 0xfd, 0x85, 0x00, 0x01, 0x00, 0x4f, 0xff, 0xf6, 0x02, 0xb0, 0x02, 0xca, 0x00, + 0x18, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x14, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x00, 0x18, 0x01, 0x18, 0x05, 0x0d, 0x16, + 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0x01, 0x2c, 0x70, 0x6d, 0x06, 0x06, 0x5c, 0x59, 0x5d, 0x05, 0x06, 0x45, 0x44, + 0x59, 0x57, 0x13, 0x63, 0x59, 0x64, 0x10, 0x45, 0x74, 0x0a, 0x67, 0x5f, 0x11, 0x32, 0x1c, 0x01, 0xaf, 0xfe, 0x4c, + 0x17, 0x32, 0x10, 0x38, 0x40, 0x5c, 0x59, 0x01, 0xd0, 0xfe, 0x29, 0x4e, 0x72, 0x3d, 0x00, 0x01, 0x00, 0x5c, 0x00, + 0x00, 0x02, 0x84, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, + 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0xa9, + 0x4d, 0x58, 0x2d, 0x05, 0x05, 0x01, 0x02, 0x0f, 0x26, 0x18, 0xe8, 0x63, 0xfe, 0x84, 0x02, 0xca, 0xfe, 0x3c, 0x29, + 0x54, 0x24, 0x24, 0x4f, 0x2f, 0x01, 0xc3, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x00, 0x03, 0xaf, 0x02, 0xca, + 0x00, 0x21, 0x00, 0x27, 0x40, 0x24, 0x1c, 0x10, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x21, 0x11, 0x19, 0x19, + 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, + 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x35, 0x23, 0x06, 0x06, 0x07, + 0x03, 0x89, 0x1e, 0x58, 0x0e, 0x02, 0x04, 0x02, 0x03, 0x0e, 0x28, 0x15, 0xc4, 0x5b, 0x14, 0x03, 0x02, 0x01, 0x03, + 0x0e, 0x1f, 0x13, 0xbb, 0x5f, 0xfe, 0xbc, 0x5b, 0x16, 0x02, 0x02, 0x03, 0x0a, 0x1a, 0x17, 0xd3, 0x02, 0xca, 0xfe, + 0x4d, 0x29, 0x58, 0x28, 0x27, 0x65, 0x2c, 0x01, 0xa4, 0xfe, 0x5e, 0x2f, 0x66, 0x25, 0x26, 0x5a, 0x2c, 0x01, 0xb0, + 0xfd, 0x36, 0x01, 0xcc, 0x21, 0x4b, 0x1f, 0x1e, 0x3e, 0x32, 0xfe, 0x37, 0x00, 0x00, 0x01, 0xff, 0xcc, 0x00, 0x00, + 0x02, 0x61, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, 0x4c, + 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, + 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x13, 0x23, 0x03, + 0x03, 0x34, 0x01, 0x23, 0x7f, 0x5a, 0x61, 0xd4, 0x62, 0xfe, 0xf2, 0x87, 0x5e, 0x66, 0xe8, 0x01, 0x7a, 0x01, 0x50, + 0xfe, 0xef, 0x01, 0x11, 0xfe, 0xac, 0xfe, 0x8a, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x01, 0x00, 0x5c, 0x00, 0x00, 0x02, + 0x59, 0x02, 0xca, 0x00, 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, + 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x96, 0x3a, 0x74, 0x59, 0x55, 0xea, 0x65, + 0xfe, 0xce, 0x37, 0x01, 0x0c, 0x01, 0xbe, 0xfe, 0x9a, 0x01, 0x66, 0xfe, 0x3f, 0xfe, 0xf7, 0x00, 0x00, 0x01, 0xff, + 0xf6, 0x00, 0x00, 0x02, 0x3d, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, + 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, + 0x07, 0x0a, 0x0e, 0x01, 0xbd, 0xfe, 0xc5, 0x11, 0x01, 0xa6, 0x0d, 0xfe, 0x43, 0x01, 0x4f, 0x10, 0x46, 0x02, 0x34, + 0x50, 0x47, 0xfd, 0xcd, 0x50, 0x00, 0x01, 0xff, 0xf7, 0xff, 0x62, 0x01, 0x72, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, + 0x40, 0x1f, 0x00, 0x02, 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, + 0x23, 0x03, 0x33, 0x07, 0x09, 0xba, 0xc1, 0x10, 0x6e, 0x9a, 0x6e, 0x10, 0x9e, 0x03, 0x68, 0x48, 0xfd, 0x28, 0x48, + 0x00, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x00, 0x01, 0x26, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, + 0x17, 0x2b, 0x33, 0x03, 0x33, 0x13, 0xd6, 0x6a, 0x50, 0x6a, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x01, 0xff, 0xb8, + 0xff, 0x62, 0x01, 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, + 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, + 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x48, 0x0f, 0x6e, 0x9a, 0x6e, + 0x10, 0xc1, 0xba, 0x9e, 0x48, 0x02, 0xd8, 0x48, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x26, 0x01, 0x0b, 0x02, 0x16, + 0x02, 0xcf, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, + 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, + 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x13, 0x33, 0x13, 0x23, 0x03, 0x03, 0x26, 0xd4, 0x32, 0xea, 0x4e, + 0xb4, 0xa0, 0x01, 0x0b, 0x01, 0xc4, 0xfe, 0x3c, 0x01, 0x67, 0xfe, 0x99, 0x00, 0x00, 0x01, 0xff, 0xa4, 0xff, 0x62, + 0x01, 0x40, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, + 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5c, 0x0f, 0x01, 0x8d, 0x0f, 0x9e, 0x44, + 0x44, 0x00, 0x01, 0x00, 0x92, 0x02, 0x5e, 0x01, 0x36, 0x02, 0xfe, 0x00, 0x0a, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, + 0x40, 0x1b, 0x09, 0x04, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x2e, 0x02, 0x27, + 0x35, 0x33, 0x16, 0x16, 0x17, 0x15, 0x01, 0x00, 0x13, 0x2b, 0x26, 0x0a, 0x5e, 0x0b, 0x27, 0x14, 0x02, 0x5e, 0x13, + 0x36, 0x38, 0x15, 0x0a, 0x25, 0x4d, 0x22, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, 0x26, 0x02, 0x22, + 0x00, 0x14, 0x00, 0x26, 0x00, 0x67, 0xb6, 0x11, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x16, 0x15, 0x01, 0x00, 0x20, 0x1e, 0x15, 0x26, 0x16, 0x26, + 0x10, 0x0f, 0x0e, 0x0d, 0x09, 0x07, 0x00, 0x14, 0x01, 0x14, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x36, + 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xc1, 0x40, 0x51, 0x27, 0x46, 0x60, + 0x3a, 0x35, 0x42, 0x10, 0x05, 0x20, 0x43, 0x72, 0x46, 0x0d, 0x04, 0x22, 0x5c, 0x1b, 0x25, 0x47, 0x3a, 0x0f, 0x08, + 0x05, 0x34, 0x2c, 0x27, 0x42, 0x32, 0x1b, 0x2c, 0x0a, 0x5d, 0x5a, 0x4b, 0x87, 0x67, 0x3c, 0x38, 0x25, 0x53, 0xfd, + 0xe8, 0x63, 0x2c, 0x41, 0x49, 0x36, 0x5c, 0x39, 0x1d, 0x31, 0x15, 0x2f, 0x3c, 0x31, 0x55, 0x6c, 0x3b, 0x36, 0x36, + 0x00, 0x00, 0x02, 0x00, 0x1c, 0xff, 0xf6, 0x02, 0x12, 0x02, 0xf8, 0x00, 0x18, 0x00, 0x27, 0x00, 0x94, 0xb5, 0x03, + 0x01, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, + 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x01, 0x06, 0x02, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x03, 0x02, 0x85, 0x00, 0x05, 0x05, 0x03, 0x61, + 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x62, 0x06, 0x01, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x17, 0x1a, 0x19, 0x01, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x12, + 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x18, 0x01, 0x18, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, + 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, + 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x0d, 0x36, 0x43, 0x10, 0x05, 0x21, 0x42, + 0xa1, 0x58, 0x26, 0x07, 0x11, 0x0c, 0x01, 0x04, 0x24, 0x55, 0x38, 0x42, 0x51, 0x24, 0x44, 0x60, 0x44, 0x28, 0x42, + 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, 0x32, 0x0a, 0x37, 0x25, 0x52, 0x02, 0xf8, 0xb4, 0x22, 0x41, 0x2b, 0x02, + 0x2c, 0x41, 0x5c, 0x5a, 0x49, 0x86, 0x69, 0x3d, 0x49, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x55, 0x6c, 0x3b, 0x30, + 0x3c, 0x00, 0x01, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xcd, 0x02, 0x22, 0x00, 0x1c, 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, + 0x02, 0x01, 0x19, 0x0c, 0x02, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x17, + 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, + 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, + 0x15, 0x06, 0x06, 0xf7, 0x59, 0x6e, 0x27, 0x49, 0x68, 0x40, 0x23, 0x46, 0x1c, 0x19, 0x14, 0x37, 0x20, 0x39, 0x56, + 0x30, 0x3f, 0x37, 0x23, 0x3f, 0x1f, 0x1c, 0x45, 0x0a, 0x64, 0x64, 0x48, 0x81, 0x62, 0x39, 0x0e, 0x0c, 0x49, 0x09, + 0x10, 0x4d, 0x80, 0x4c, 0x3d, 0x43, 0x14, 0x0d, 0x4a, 0x0e, 0x12, 0x00, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x02, + 0x55, 0x02, 0xf8, 0x00, 0x17, 0x00, 0x26, 0x00, 0x95, 0xb6, 0x14, 0x0b, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x29, + 0x50, 0x58, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, + 0x40, 0x21, 0x00, 0x02, 0x01, 0x02, 0x85, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, + 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x59, 0x40, + 0x17, 0x19, 0x18, 0x01, 0x00, 0x21, 0x1f, 0x18, 0x26, 0x19, 0x26, 0x13, 0x12, 0x11, 0x10, 0x09, 0x07, 0x00, 0x17, + 0x01, 0x17, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, + 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0xc1, 0x40, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x41, 0x10, 0x05, 0x05, 0x09, 0x08, 0x25, + 0x57, 0xa1, 0x48, 0x0b, 0x04, 0x24, 0x56, 0x1a, 0x21, 0x44, 0x3a, 0x23, 0x2f, 0x35, 0x28, 0x41, 0x30, 0x1a, 0x0a, + 0x5c, 0x5b, 0x4a, 0x85, 0x69, 0x3c, 0x37, 0x25, 0x22, 0x3e, 0x24, 0xaf, 0xfd, 0x08, 0x63, 0x2d, 0x40, 0x49, 0x31, + 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x02, 0x00, 0x30, 0xff, 0xf6, 0x01, 0xd5, 0x02, + 0x22, 0x00, 0x1c, 0x00, 0x27, 0x00, 0x43, 0x40, 0x40, 0x19, 0x01, 0x03, 0x02, 0x1a, 0x01, 0x00, 0x03, 0x02, 0x4c, + 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1e, 0x1d, 0x01, 0x00, 0x25, 0x23, 0x1d, + 0x27, 0x1e, 0x27, 0x17, 0x15, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x06, 0x06, 0x15, 0x14, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0xf2, + 0x5d, 0x65, 0x25, 0x46, 0x63, 0x3e, 0x4c, 0x4d, 0x41, 0x8a, 0x6e, 0x11, 0x01, 0x01, 0x3c, 0x3d, 0x26, 0x44, 0x28, + 0x26, 0x49, 0x86, 0x3c, 0x66, 0x3e, 0x23, 0x25, 0x30, 0x59, 0x16, 0x0a, 0x6d, 0x5d, 0x40, 0x7d, 0x67, 0x3e, 0x42, + 0x3b, 0x34, 0x56, 0x33, 0x09, 0x14, 0x08, 0x3d, 0x47, 0x16, 0x13, 0x4b, 0x11, 0x16, 0x01, 0x39, 0x15, 0x31, 0x29, + 0x1a, 0x21, 0x59, 0x51, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x24, 0x00, 0x77, 0x40, + 0x12, 0x16, 0x01, 0x04, 0x03, 0x17, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, + 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, + 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x69, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, + 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, + 0x15, 0x01, 0x00, 0x21, 0x20, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x24, 0x01, 0x24, + 0x08, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, + 0x06, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x24, 0x28, 0x0c, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, + 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x70, 0x12, 0x4c, 0xf0, + 0x06, 0x04, 0x4a, 0x04, 0x07, 0x3b, 0x37, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, + 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x19, 0xff, 0x10, 0x02, 0x27, 0x02, + 0x22, 0x00, 0x23, 0x00, 0x32, 0x00, 0x80, 0x40, 0x0f, 0x1d, 0x0e, 0x02, 0x05, 0x06, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, 0x61, 0x04, 0x01, + 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x06, 0x06, + 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, 0x01, 0x00, 0x2d, + 0x2b, 0x24, 0x32, 0x25, 0x32, 0x20, 0x1f, 0x1b, 0x19, 0x13, 0x11, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x09, 0x0d, + 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x23, 0x06, + 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x06, 0x06, 0x03, + 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xba, 0x31, 0x53, 0x1d, 0x1a, 0x59, 0x2b, + 0x3e, 0x50, 0x10, 0x09, 0x05, 0x0f, 0x05, 0x04, 0x22, 0x57, 0x38, 0x41, 0x51, 0x24, 0x45, 0x61, 0x3d, 0x36, 0x42, + 0x10, 0x04, 0x21, 0x43, 0x7a, 0x18, 0x7b, 0x3b, 0x22, 0x44, 0x39, 0x22, 0x2d, 0x35, 0x28, 0x42, 0x30, 0x1a, 0xf0, + 0x13, 0x0f, 0x51, 0x10, 0x1a, 0x3c, 0x46, 0x26, 0x17, 0x38, 0x13, 0x2c, 0x41, 0x5d, 0x5a, 0x49, 0x86, 0x69, 0x3d, + 0x38, 0x25, 0x53, 0xfd, 0xc9, 0x71, 0x60, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x30, 0x3c, 0x33, 0x56, 0x6c, 0x38, + 0x6c, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x0b, 0x02, 0xf8, 0x00, 0x1e, 0x00, 0x50, 0xb5, 0x06, 0x01, 0x02, + 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x17, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, + 0x01, 0x00, 0x85, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1e, 0x25, 0x16, 0x28, 0x11, 0x06, 0x0d, 0x1a, 0x2b, + 0x33, 0x13, 0x33, 0x07, 0x06, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, + 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0xa1, 0x58, 0x2b, 0x06, 0x12, 0x08, 0x05, + 0x13, 0x34, 0x43, 0x2b, 0x3e, 0x49, 0x06, 0x05, 0x46, 0x58, 0x47, 0x09, 0x21, 0x25, 0x22, 0x4f, 0x43, 0x13, 0x31, + 0x02, 0xf8, 0xc5, 0x1e, 0x41, 0x20, 0x19, 0x32, 0x22, 0x45, 0x44, 0x13, 0x28, 0x17, 0xfe, 0xba, 0x01, 0x50, 0x2d, + 0x15, 0x21, 0x25, 0x2f, 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x02, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x0e, 0x02, 0xe0, 0x00, + 0x0a, 0x00, 0x0e, 0x00, 0x4d, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x17, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x15, + 0x00, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, + 0x03, 0x4e, 0x59, 0x40, 0x13, 0x0b, 0x0b, 0x01, 0x00, 0x0b, 0x0e, 0x0b, 0x0e, 0x0d, 0x0c, 0x07, 0x05, 0x00, 0x0a, + 0x01, 0x0a, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, 0x14, 0x06, 0x03, 0x13, + 0x33, 0x03, 0xd5, 0x15, 0x1b, 0x1f, 0x1c, 0x2e, 0x24, 0xce, 0x72, 0x58, 0x72, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, + 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, 0xe8, 0x00, 0x02, 0xff, 0x82, 0xff, 0x10, 0x01, 0x0d, 0x02, 0xe0, + 0x00, 0x0a, 0x00, 0x18, 0x00, 0x65, 0x40, 0x0a, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x4b, + 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x1c, 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x1a, 0x00, + 0x01, 0x05, 0x01, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, + 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x15, 0x0c, 0x0b, 0x01, 0x00, 0x15, 0x14, 0x12, 0x10, 0x0b, 0x18, + 0x0c, 0x18, 0x07, 0x05, 0x00, 0x0a, 0x01, 0x0a, 0x07, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, + 0x32, 0x15, 0x14, 0x06, 0x01, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0xd4, + 0x14, 0x1b, 0x1f, 0x1c, 0x2d, 0x24, 0xfe, 0xd7, 0x25, 0x19, 0x0c, 0x1e, 0x10, 0x3d, 0x15, 0x80, 0x57, 0x82, 0x10, + 0x49, 0x02, 0x71, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfc, 0x9f, 0x0a, 0x4a, 0x04, 0x07, 0x62, 0x02, 0x5d, + 0xfd, 0x9b, 0x4b, 0x58, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x0d, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x47, + 0xb7, 0x0d, 0x0a, 0x06, 0x03, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x12, 0x00, 0x00, 0x00, + 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x12, 0x00, + 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, + 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x06, + 0x06, 0x07, 0x33, 0x13, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x1b, 0xa1, 0x59, 0x41, 0x11, 0x19, 0x05, 0x02, + 0xfe, 0x68, 0xe6, 0x8f, 0x61, 0x71, 0x48, 0x28, 0x02, 0xf8, 0xfe, 0xd2, 0x50, 0x57, 0x0e, 0x01, 0x03, 0xe6, 0xfe, + 0xce, 0xfb, 0x39, 0xc2, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x15, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, + 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x1b, 0xa2, 0x58, 0xa2, 0x02, 0xf8, + 0xfd, 0x08, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x33, 0x02, 0x22, 0x00, 0x30, 0x00, 0x56, 0xb6, 0x0b, 0x03, + 0x02, 0x03, 0x04, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, + 0x01, 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, + 0x00, 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, + 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x25, 0x14, 0x26, 0x16, + 0x26, 0x25, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x07, 0x07, 0x23, 0x13, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, 0x48, + 0x0b, 0x05, 0x12, 0x31, 0x41, 0x29, 0x37, 0x3b, 0x06, 0x04, 0x14, 0x37, 0x44, 0x29, 0x3e, 0x44, 0x06, 0x05, 0x45, + 0x59, 0x48, 0x05, 0x04, 0x21, 0x23, 0x20, 0x49, 0x3f, 0x11, 0x33, 0x58, 0x47, 0x09, 0x1e, 0x23, 0x20, 0x4a, 0x40, + 0x13, 0x31, 0x02, 0x18, 0x63, 0x19, 0x32, 0x22, 0x3f, 0x38, 0x1e, 0x36, 0x23, 0x44, 0x40, 0x18, 0x29, 0x17, 0xfe, + 0xba, 0x01, 0x50, 0x17, 0x20, 0x0f, 0x1e, 0x24, 0x30, 0x65, 0x51, 0xf2, 0x01, 0x50, 0x2d, 0x15, 0x21, 0x25, 0x2f, + 0x6a, 0x58, 0xe7, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x25, 0x00, 0x1b, 0x00, 0x4c, 0xb5, + 0x03, 0x01, 0x02, 0x03, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, 0x61, 0x01, + 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x00, 0x00, + 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x1b, 0x25, 0x16, 0x25, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, + 0x13, 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x03, 0x23, 0x13, 0x36, 0x36, 0x35, + 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x18, 0x73, 0x4e, 0x0b, 0x01, 0x13, 0x33, 0x44, 0x2b, 0x41, 0x49, 0x07, + 0x04, 0x47, 0x5e, 0x48, 0x05, 0x05, 0x44, 0x21, 0x4d, 0x43, 0x13, 0x32, 0x02, 0x1b, 0x63, 0x19, 0x32, 0x22, 0x47, + 0x40, 0x17, 0x30, 0x12, 0xfe, 0xbb, 0x01, 0x51, 0x17, 0x1f, 0x0e, 0x40, 0x2e, 0x68, 0x58, 0xe7, 0x00, 0x02, 0x00, + 0x30, 0xff, 0xf8, 0x02, 0x04, 0x02, 0x1f, 0x00, 0x0f, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x11, 0x10, 0x01, 0x00, 0x19, 0x17, 0x10, 0x1e, 0x11, 0x1e, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, + 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, + 0x35, 0x34, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf8, 0x5d, 0x6b, 0x22, 0x43, 0x65, 0x42, 0x5e, + 0x6a, 0x22, 0x43, 0x64, 0x3e, 0x30, 0x4e, 0x2f, 0x15, 0x30, 0x28, 0x37, 0x51, 0x2c, 0x3d, 0x08, 0x6f, 0x5f, 0x3e, + 0x7a, 0x64, 0x3d, 0x6f, 0x60, 0x3d, 0x7a, 0x64, 0x3d, 0x49, 0x43, 0x7e, 0x58, 0x1e, 0x39, 0x25, 0x4b, 0x7d, 0x4b, + 0x3e, 0x44, 0x00, 0x02, 0xff, 0xea, 0xff, 0x10, 0x02, 0x12, 0x02, 0x21, 0x00, 0x17, 0x00, 0x26, 0x00, 0x68, 0xb6, + 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, 0xb0, 0x1b, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, + 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, + 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x14, 0x19, 0x18, 0x00, 0x00, 0x20, 0x1e, 0x18, 0x26, 0x19, 0x26, 0x00, 0x17, 0x00, + 0x17, 0x26, 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x16, 0xa4, 0x48, 0x0c, 0x04, 0x23, 0x58, 0x38, 0x41, 0x50, 0x24, 0x44, 0x61, + 0x3c, 0x36, 0x42, 0x11, 0x05, 0x01, 0x08, 0x04, 0x31, 0xc5, 0x28, 0x42, 0x2f, 0x19, 0x55, 0x21, 0x45, 0x3a, 0x23, + 0x32, 0xf0, 0x03, 0x08, 0x64, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3c, 0x37, 0x25, 0x10, 0x39, 0x12, 0xe7, + 0x01, 0x2f, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x31, 0x54, 0x6c, 0x3c, 0x30, 0x3c, 0x00, 0x02, 0x00, 0x30, 0xff, 0x10, + 0x02, 0x26, 0x02, 0x22, 0x00, 0x17, 0x00, 0x26, 0x00, 0x61, 0xb6, 0x12, 0x03, 0x02, 0x04, 0x05, 0x01, 0x4c, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, + 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x19, 0x18, 0x21, 0x1f, + 0x18, 0x26, 0x19, 0x26, 0x11, 0x14, 0x26, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x5a, 0x05, 0x11, 0x07, 0x04, 0x22, 0x57, 0x38, + 0x41, 0x51, 0x24, 0x45, 0x62, 0x3d, 0x35, 0x41, 0x10, 0x05, 0x21, 0x42, 0xa5, 0x57, 0x4b, 0x21, 0x44, 0x39, 0x23, + 0x2e, 0x34, 0x28, 0x42, 0x30, 0x1a, 0x0c, 0x13, 0x43, 0x19, 0x2c, 0x41, 0x5c, 0x5b, 0x49, 0x86, 0x69, 0x3d, 0x38, + 0x25, 0x53, 0xfc, 0xf8, 0x01, 0x2f, 0x32, 0x55, 0x6c, 0x3a, 0x2c, 0x40, 0x33, 0x56, 0x6c, 0x38, 0x6c, 0x00, 0x00, + 0x01, 0x00, 0x1c, 0x00, 0x00, 0x01, 0xad, 0x02, 0x22, 0x00, 0x13, 0x00, 0x63, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x0b, 0x0c, 0x03, 0x02, 0x03, 0x02, 0x01, 0x4c, 0x0b, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0b, 0x0b, 0x01, 0x00, 0x01, + 0x0c, 0x03, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x24, 0x25, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, + 0x33, 0x07, 0x33, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x1c, 0x72, + 0x48, 0x0b, 0x05, 0x15, 0x2e, 0x3a, 0x26, 0x0e, 0x1f, 0x0d, 0x13, 0x1b, 0x18, 0x32, 0x4e, 0x34, 0x0b, 0x34, 0x02, + 0x18, 0x63, 0x1c, 0x31, 0x20, 0x03, 0x04, 0x4f, 0x06, 0x42, 0x66, 0x35, 0xf5, 0x00, 0x01, 0x00, 0x05, 0xff, 0xf6, + 0x01, 0x9c, 0x02, 0x22, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x16, 0x01, 0x03, 0x02, 0x17, 0x04, 0x02, 0x01, 0x03, + 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x14, 0x12, 0x08, 0x06, 0x00, 0x26, + 0x01, 0x26, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, + 0x17, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x9b, 0x31, 0x49, 0x1c, 0x1a, 0x4f, 0x2a, 0x3b, 0x3e, 0x26, 0x34, 0x39, 0x3a, + 0x63, 0x53, 0x31, 0x53, 0x1e, 0x1c, 0x1a, 0x40, 0x2c, 0x2b, 0x33, 0x23, 0x35, 0x22, 0x36, 0x1f, 0x71, 0x0a, 0x13, + 0x0f, 0x51, 0x10, 0x1b, 0x2f, 0x25, 0x1d, 0x27, 0x1d, 0x20, 0x44, 0x33, 0x44, 0x54, 0x17, 0x0e, 0x46, 0x0c, 0x15, + 0x29, 0x20, 0x1a, 0x27, 0x1d, 0x14, 0x28, 0x34, 0x26, 0x51, 0x54, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, + 0x6c, 0x02, 0x92, 0x00, 0x1c, 0x00, 0x66, 0x40, 0x0a, 0x19, 0x01, 0x05, 0x01, 0x1a, 0x01, 0x00, 0x05, 0x02, 0x4c, + 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, + 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, + 0x1c, 0x00, 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, + 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, + 0x37, 0x13, 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x06, 0xb9, 0x36, 0x4a, 0x09, 0x3d, 0x53, 0x08, 0x5a, 0x3e, 0x34, 0x1b, 0x87, 0x0e, 0x86, 0x3e, + 0x03, 0x06, 0x19, 0x1c, 0x12, 0x22, 0x13, 0x0c, 0x32, 0x0a, 0x34, 0x41, 0x20, 0x27, 0x01, 0x23, 0x28, 0x26, 0x6f, + 0x7a, 0x43, 0xfe, 0xdc, 0x0d, 0x21, 0x0e, 0x17, 0x20, 0x07, 0x06, 0x43, 0x06, 0x0c, 0x00, 0x01, 0x00, 0x37, 0xff, + 0xf6, 0x02, 0x26, 0x02, 0x18, 0x00, 0x1b, 0x00, 0x50, 0xb5, 0x17, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, + 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x16, 0x15, 0x14, + 0x13, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, + 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, + 0x0e, 0x02, 0xbd, 0x3d, 0x49, 0x07, 0x04, 0x46, 0x59, 0x48, 0x09, 0x21, 0x25, 0x22, 0x4f, 0x44, 0x13, 0x31, 0x57, + 0x72, 0x48, 0x0b, 0x05, 0x13, 0x33, 0x43, 0x0a, 0x44, 0x41, 0x17, 0x29, 0x16, 0x01, 0x47, 0xfe, 0xaf, 0x2b, 0x18, + 0x20, 0x25, 0x30, 0x6a, 0x58, 0xe7, 0xfd, 0xe8, 0x63, 0x18, 0x33, 0x22, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x00, + 0x02, 0x03, 0x02, 0x18, 0x00, 0x0f, 0x00, 0x21, 0x40, 0x1e, 0x07, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, + 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x1b, 0x11, 0x04, + 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, 0x01, 0x6e, 0x3e, + 0x58, 0x1e, 0x03, 0x05, 0x03, 0x03, 0x0b, 0x1e, 0x1f, 0x0b, 0x9e, 0x5e, 0xfe, 0xde, 0x02, 0x18, 0xfe, 0xd6, 0x1a, + 0x46, 0x3d, 0x0e, 0x19, 0x40, 0x40, 0x15, 0x01, 0x27, 0xfd, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x39, 0x00, 0x00, 0x02, + 0xf9, 0x02, 0x18, 0x00, 0x22, 0x00, 0x27, 0x40, 0x24, 0x1d, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, + 0x11, 0x19, 0x1a, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, + 0x13, 0x33, 0x13, 0x16, 0x16, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x26, 0x36, 0x35, 0x23, + 0x06, 0x06, 0x07, 0x03, 0x4f, 0x16, 0x56, 0x08, 0x02, 0x04, 0x02, 0x04, 0x08, 0x16, 0x19, 0x0a, 0x8d, 0x5f, 0x11, + 0x01, 0x02, 0x02, 0x04, 0x0d, 0x28, 0x18, 0x75, 0x5d, 0xf8, 0x6a, 0x0f, 0x02, 0x01, 0x04, 0x0d, 0x1b, 0x18, 0x8c, + 0x02, 0x18, 0xfe, 0xe2, 0x37, 0x59, 0x1d, 0x15, 0x39, 0x39, 0x15, 0x01, 0x2f, 0xfe, 0xe1, 0x25, 0x61, 0x26, 0x26, + 0x67, 0x37, 0x01, 0x07, 0xfd, 0xe8, 0x01, 0x22, 0x28, 0x4a, 0x2f, 0x25, 0x3f, 0x33, 0xfe, 0xd4, 0x00, 0x01, 0xff, + 0xdb, 0x00, 0x00, 0x01, 0xfe, 0x02, 0x18, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, + 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, + 0x13, 0x23, 0x27, 0x07, 0x25, 0xe8, 0x74, 0x59, 0x53, 0x9d, 0x66, 0xdf, 0x7b, 0x59, 0x5b, 0xa5, 0x01, 0x14, 0x01, + 0x04, 0xc6, 0xc6, 0xfe, 0xf8, 0xfe, 0xf0, 0xd0, 0xd0, 0x00, 0x01, 0xff, 0xa2, 0xff, 0x10, 0x02, 0x03, 0x02, 0x18, + 0x00, 0x1c, 0x00, 0x30, 0x40, 0x2d, 0x12, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x03, + 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x01, 0x00, + 0x19, 0x18, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x05, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, 0x37, 0x13, 0x33, + 0x01, 0x06, 0x06, 0x19, 0x18, 0x1f, 0x0e, 0x0e, 0x20, 0x12, 0x29, 0x39, 0x1a, 0x23, 0x51, 0x58, 0x23, 0x05, 0x05, + 0x03, 0x03, 0x07, 0x1b, 0x20, 0x0c, 0x9c, 0x5e, 0xfe, 0xac, 0x28, 0x59, 0xf0, 0x06, 0x04, 0x47, 0x04, 0x05, 0x32, + 0x30, 0x3e, 0x02, 0x20, 0xfe, 0xf7, 0x20, 0x4d, 0x45, 0x15, 0x10, 0x40, 0x44, 0x16, 0x01, 0x26, 0xfd, 0x8e, 0x4b, + 0x4b, 0x00, 0x01, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xb7, 0x02, 0x18, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, + 0x21, 0x07, 0x01, 0x33, 0x07, 0x0f, 0x0c, 0x01, 0x4d, 0xe6, 0x0e, 0x01, 0x45, 0x0e, 0xfe, 0xb9, 0xff, 0x0d, 0x3c, + 0x01, 0x9a, 0x42, 0x47, 0xfe, 0x71, 0x42, 0x00, 0x01, 0x00, 0x0b, 0xff, 0x62, 0x01, 0x90, 0x02, 0xca, 0x00, 0x2c, + 0x00, 0x37, 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, + 0x05, 0x06, 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x01, + 0x00, 0x2b, 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, + 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, + 0x36, 0x33, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x15, 0xd9, 0x46, 0x4b, 0x06, 0x04, 0x18, 0x03, 0x04, 0x66, 0x11, 0x3a, 0x46, + 0x0a, 0x21, 0x11, 0x53, 0x53, 0x12, 0x0f, 0x2c, 0x32, 0x0b, 0x23, 0x0b, 0x39, 0x3b, 0x27, 0x24, 0x05, 0x04, 0x16, + 0x03, 0x04, 0x29, 0x22, 0x9e, 0x35, 0x39, 0x10, 0x21, 0x13, 0x69, 0x10, 0x1a, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, + 0x4f, 0x3f, 0x49, 0x1e, 0x2f, 0x9c, 0x33, 0x42, 0x0a, 0x02, 0x0a, 0x37, 0x27, 0x0d, 0x22, 0x10, 0x66, 0x0d, 0x17, + 0x0a, 0x1d, 0x14, 0x49, 0x00, 0x00, 0x01, 0x01, 0x04, 0xff, 0x0f, 0x01, 0x4c, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x30, + 0x4b, 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, + 0x1b, 0x40, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x05, 0x11, 0x33, 0x11, 0x01, 0x04, 0x48, 0xf1, 0x03, + 0xe9, 0xfc, 0x17, 0x00, 0x01, 0xff, 0xdb, 0xff, 0x62, 0x01, 0x59, 0x02, 0xca, 0x00, 0x2d, 0x00, 0x31, 0x40, 0x2e, + 0x07, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x2c, 0x2b, 0x25, 0x24, 0x23, 0x22, + 0x18, 0x16, 0x15, 0x14, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, 0x26, + 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x07, 0x07, 0x06, 0x06, 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x0e, 0x02, 0x23, 0x23, 0x25, 0x30, 0x38, + 0x0a, 0x23, 0x0b, 0x3a, 0x3a, 0x27, 0x23, 0x05, 0x04, 0x17, 0x03, 0x04, 0x2e, 0x29, 0x0f, 0x06, 0x48, 0x4b, 0x05, + 0x05, 0x18, 0x03, 0x05, 0x66, 0x10, 0x3a, 0x45, 0x0b, 0x21, 0x0c, 0x2e, 0x4a, 0x38, 0x07, 0x55, 0x1e, 0x2f, 0x9c, + 0x33, 0x41, 0x0a, 0x03, 0x0b, 0x35, 0x27, 0x0e, 0x21, 0x10, 0x67, 0x0d, 0x17, 0x0a, 0x1d, 0x14, 0x49, 0x35, 0x39, + 0x10, 0x21, 0x13, 0x6a, 0x10, 0x19, 0x0c, 0x46, 0x49, 0x2a, 0x33, 0x9d, 0x38, 0x3e, 0x18, 0x00, 0x00, 0x01, 0x00, + 0x46, 0x01, 0x1f, 0x02, 0x1d, 0x01, 0xa2, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, + 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, + 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, + 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, + 0x01, 0x21, 0x24, 0x2f, 0x16, 0x1c, 0x3e, 0x18, 0x30, 0x48, 0x1d, 0x39, 0x2e, 0x24, 0x2f, 0x15, 0x1d, 0x3e, 0x18, + 0x31, 0x47, 0x1c, 0x3b, 0x01, 0x3f, 0x10, 0x0b, 0x22, 0x19, 0x4e, 0x35, 0x0c, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x4d, + 0x36, 0x0d, 0x00, 0x01, 0x00, 0x47, 0x01, 0xa0, 0x01, 0x8e, 0x03, 0x55, 0x00, 0x19, 0x00, 0x32, 0x40, 0x2f, 0x0b, + 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, + 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x19, 0x18, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, 0x33, 0x07, 0x47, 0x0c, 0x81, + 0x3c, 0x38, 0x1d, 0x1c, 0x2f, 0x30, 0x1f, 0x1f, 0x43, 0x28, 0x2a, 0x32, 0x17, 0x17, 0x36, 0x2e, 0x68, 0xbf, 0x0d, + 0x01, 0xa0, 0x37, 0x6e, 0x34, 0x44, 0x27, 0x19, 0x1e, 0x27, 0x2f, 0x19, 0x19, 0x1e, 0x2f, 0x19, 0x21, 0x38, 0x3c, + 0x26, 0x57, 0x3d, 0x00, 0x01, 0x00, 0x51, 0x01, 0x99, 0x01, 0x8c, 0x03, 0x56, 0x00, 0x27, 0x00, 0x4d, 0x40, 0x4a, + 0x18, 0x01, 0x04, 0x05, 0x17, 0x01, 0x03, 0x04, 0x21, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, + 0x1c, 0x1a, 0x15, 0x13, 0x10, 0x0e, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x27, 0x01, 0x27, 0x07, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x07, 0x06, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, + 0x06, 0xc4, 0x21, 0x3b, 0x17, 0x1a, 0x3e, 0x1d, 0x32, 0x31, 0x54, 0x2e, 0x0c, 0x2e, 0x2e, 0x38, 0x40, 0x1a, 0x2d, + 0x15, 0x1c, 0x17, 0x44, 0x2a, 0x3c, 0x3c, 0x36, 0x30, 0x23, 0x25, 0x53, 0x01, 0x99, 0x0f, 0x0c, 0x41, 0x0f, 0x14, + 0x2c, 0x25, 0x40, 0x37, 0x27, 0x22, 0x3b, 0x02, 0x01, 0x11, 0x0f, 0x30, 0x12, 0x19, 0x39, 0x2c, 0x2d, 0x37, 0x0d, + 0x04, 0x08, 0x31, 0x22, 0x3a, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x94, 0x01, 0x9f, 0x01, 0x60, 0x03, 0x4b, 0x00, 0x0c, + 0x00, 0x19, 0x40, 0x16, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x00, 0x01, + 0x01, 0x76, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x37, 0x33, + 0x03, 0x23, 0xf3, 0x05, 0x11, 0x06, 0x08, 0x17, 0x0c, 0x34, 0x1c, 0x8e, 0x3e, 0x5b, 0x47, 0x02, 0x9a, 0x19, 0x3f, + 0x15, 0x07, 0x15, 0x09, 0x22, 0x2f, 0x5c, 0xfe, 0x54, 0x00, 0x01, 0xff, 0x10, 0x00, 0x00, 0x01, 0x71, 0x02, 0xca, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x23, 0x01, 0x33, 0x01, 0xf0, 0x02, 0x12, 0x4f, 0xfd, + 0xee, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x00, 0x02, 0x00, 0x4b, 0x01, 0xa0, 0x01, 0x8a, 0x03, 0x4f, 0x00, 0x0a, 0x00, + 0x14, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x0d, 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, + 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, + 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, + 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, + 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, + 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, + 0x36, 0x36, 0x37, 0x0e, 0x02, 0x07, 0xe9, 0x14, 0xb2, 0x0b, 0xeb, 0x47, 0x3b, 0x3d, 0x0b, 0x3f, 0x14, 0x8e, 0x6c, + 0x14, 0x06, 0x0a, 0x07, 0x04, 0x13, 0x16, 0x08, 0x01, 0xa0, 0x61, 0x34, 0x01, 0x1a, 0xfe, 0xed, 0x3b, 0x61, 0x9c, + 0x5c, 0x1a, 0x2f, 0x18, 0x07, 0x1b, 0x1c, 0x09, 0x00, 0x00, 0x01, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x98, 0x03, 0x4d, + 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, + 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, + 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x33, 0x07, + 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc6, 0x3b, 0x2c, 0x1a, 0x36, 0x1c, 0x32, 0x36, + 0x2e, 0x21, 0x10, 0x20, 0x11, 0x1b, 0x3c, 0xd4, 0x0c, 0x9b, 0x1f, 0x09, 0x17, 0x0d, 0x38, 0x3f, 0x22, 0x4d, 0x01, + 0x99, 0x19, 0x43, 0x10, 0x12, 0x33, 0x2a, 0x22, 0x22, 0x05, 0x06, 0x17, 0xcd, 0x3e, 0x69, 0x02, 0x04, 0x3e, 0x37, + 0x25, 0x49, 0x30, 0x00, 0x00, 0x01, 0x00, 0x71, 0x01, 0xa1, 0x01, 0xae, 0x03, 0x4d, 0x00, 0x06, 0x00, 0x24, 0x40, + 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, + 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, + 0x37, 0x21, 0x07, 0x03, 0x71, 0xe4, 0xc0, 0x0d, 0x01, 0x0c, 0x0a, 0xe4, 0x01, 0xa1, 0x01, 0x71, 0x3b, 0x30, 0xfe, + 0x84, 0x00, 0x00, 0x03, 0x00, 0x58, 0x01, 0x99, 0x01, 0x94, 0x03, 0x55, 0x00, 0x16, 0x00, 0x22, 0x00, 0x2e, 0x00, + 0x39, 0x40, 0x36, 0x29, 0x11, 0x05, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, + 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x03, 0x00, 0x51, + 0x24, 0x23, 0x01, 0x00, 0x23, 0x2e, 0x24, 0x2e, 0x1e, 0x1c, 0x0c, 0x0a, 0x00, 0x16, 0x01, 0x16, 0x06, 0x0c, 0x16, + 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x07, 0x16, + 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xd7, 0x38, 0x47, 0x6e, 0x18, 0x1d, 0x4c, 0x43, 0x3a, + 0x3a, 0x35, 0x2e, 0x1e, 0x24, 0x55, 0x1b, 0x1b, 0x32, 0x1f, 0x18, 0x21, 0x24, 0x1c, 0x13, 0x26, 0x2a, 0x23, 0x17, + 0x25, 0x33, 0x25, 0x01, 0x99, 0x39, 0x32, 0x58, 0x29, 0x12, 0x29, 0x23, 0x32, 0x40, 0x3a, 0x28, 0x28, 0x3a, 0x10, + 0x13, 0x30, 0x25, 0x37, 0x49, 0x01, 0x04, 0x0a, 0x22, 0x24, 0x17, 0x1a, 0x22, 0x1a, 0x1a, 0x1f, 0xd9, 0x01, 0x29, + 0x1f, 0x1a, 0x28, 0x0c, 0x0d, 0x2a, 0x23, 0x1b, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x65, 0x01, 0x98, 0x01, 0x96, 0x03, + 0x59, 0x00, 0x0e, 0x00, 0x1d, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, + 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, + 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1d, 0x10, 0x1d, 0x09, 0x07, 0x00, 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, + 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0xdc, 0x39, 0x3e, 0x13, 0x2b, 0x47, 0x33, 0x79, 0x15, 0x2d, 0x47, 0x2c, 0x1d, + 0x2a, 0x1b, 0x0e, 0x38, 0x1a, 0x29, 0x1d, 0x0f, 0x1a, 0x01, 0x98, 0x4d, 0x4c, 0x2d, 0x67, 0x5a, 0x3a, 0x90, 0x37, + 0x6c, 0x59, 0x35, 0x3e, 0x2c, 0x49, 0x56, 0x29, 0x51, 0x2a, 0x45, 0x52, 0x29, 0x2c, 0x2f, 0x00, 0x02, 0x00, 0x6a, + 0x01, 0x99, 0x01, 0x9d, 0x03, 0x53, 0x00, 0x1a, 0x00, 0x27, 0x00, 0x4b, 0x40, 0x48, 0x09, 0x01, 0x02, 0x01, 0x0a, + 0x01, 0x03, 0x02, 0x10, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, + 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1c, 0x1b, 0x01, 0x00, 0x22, 0x20, 0x1b, 0x27, 0x1c, 0x27, 0x15, 0x13, 0x0e, + 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, + 0x32, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe2, 0x35, 0x43, 0x33, 0x6c, 0x53, + 0x23, 0x1e, 0x0f, 0x0c, 0x21, 0x13, 0x3c, 0x4d, 0x0f, 0x04, 0x0b, 0x2f, 0x25, 0x2f, 0x38, 0x22, 0x46, 0x30, 0x29, + 0x2c, 0x1c, 0x1d, 0x23, 0x27, 0x0e, 0x1c, 0x01, 0x99, 0x44, 0x44, 0x52, 0x8b, 0x55, 0x08, 0x3b, 0x04, 0x05, 0x4e, + 0x45, 0x0e, 0x20, 0x3c, 0x35, 0x2a, 0x4e, 0x32, 0x3a, 0x41, 0x2a, 0x1d, 0x21, 0x24, 0x2d, 0x0d, 0x1d, 0x2e, 0x00, + 0x00, 0x02, 0x00, 0x5f, 0x01, 0x99, 0x01, 0x91, 0x03, 0x53, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x11, + 0x01, 0x03, 0x04, 0x0a, 0x01, 0x02, 0x03, 0x09, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, + 0x00, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, + 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, + 0x16, 0x14, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, + 0x35, 0x34, 0x36, 0x36, 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x18, 0x36, 0x43, + 0x37, 0x6c, 0x50, 0x22, 0x1d, 0x0c, 0x27, 0x13, 0x2f, 0x42, 0x28, 0x06, 0x02, 0x11, 0x34, 0x1c, 0x2e, 0x38, 0x22, + 0x46, 0x14, 0x26, 0x32, 0x1b, 0x21, 0x29, 0x2c, 0x03, 0x53, 0x43, 0x45, 0x52, 0x8b, 0x55, 0x08, 0x3f, 0x05, 0x08, + 0x2e, 0x46, 0x25, 0x1a, 0x19, 0x3c, 0x34, 0x2a, 0x4e, 0x32, 0xe2, 0x37, 0x27, 0x1d, 0x2d, 0x41, 0x2a, 0x3d, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, 0x01, 0xbb, 0x02, 0xfd, 0x00, 0x18, 0x00, 0x35, 0x40, 0x32, 0x0c, 0x01, 0x02, + 0x01, 0x0d, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, 0x00, + 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x18, 0x11, 0x13, 0x25, 0x26, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, + 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, + 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfe, + 0x2b, 0x00, 0x01, 0xff, 0x90, 0xff, 0x10, 0x02, 0xfb, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x93, 0x40, 0x16, 0x27, 0x16, + 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x02, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, + 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, + 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, + 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x25, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, + 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, + 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x21, 0x01, 0x00, 0x41, 0x40, 0x3d, + 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, + 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x0e, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, + 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, + 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, + 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, + 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, + 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, + 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, + 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, + 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x00, 0x00, 0x03, 0xff, 0x90, 0xff, 0x10, 0x03, 0x8c, 0x02, 0xfd, 0x00, 0x44, + 0x00, 0x4f, 0x00, 0x53, 0x01, 0x05, 0x40, 0x16, 0x27, 0x16, 0x02, 0x0e, 0x03, 0x28, 0x17, 0x02, 0x0d, 0x04, 0x39, + 0x04, 0x02, 0x01, 0x10, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x1d, 0x50, 0x58, 0x40, 0x39, 0x07, + 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, + 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, + 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x37, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x12, 0x01, + 0x0d, 0x0d, 0x0e, 0x61, 0x00, 0x0e, 0x0e, 0x70, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, + 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, + 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x35, 0x06, 0x01, 0x03, 0x07, 0x01, 0x04, 0x0d, 0x03, 0x04, 0x69, 0x00, + 0x0e, 0x12, 0x01, 0x0d, 0x05, 0x0e, 0x0d, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, + 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x31, 0x50, 0x50, 0x46, 0x45, 0x01, 0x00, 0x50, 0x53, 0x50, 0x53, 0x52, + 0x51, 0x4c, 0x4a, 0x45, 0x4f, 0x46, 0x4f, 0x41, 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, + 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x14, 0x0d, 0x16, + 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x06, 0x06, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x15, + 0x14, 0x06, 0x03, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, + 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, + 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, + 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x03, 0x3b, 0x13, + 0x1c, 0x1f, 0x1c, 0x2d, 0x24, 0xce, 0x73, 0x58, 0x73, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, + 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, + 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, + 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0x03, 0x61, 0x19, 0x16, 0x1a, 0x26, 0x2d, 0x1f, 0x23, 0xfd, 0x8f, 0x02, 0x18, 0xfd, + 0xe8, 0x00, 0x00, 0x02, 0xff, 0x90, 0xff, 0x10, 0x03, 0x93, 0x02, 0xfd, 0x00, 0x44, 0x00, 0x48, 0x01, 0x04, 0x4b, + 0xb0, 0x2d, 0x50, 0x58, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x03, 0x28, 0x17, 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, + 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x27, 0x16, 0x02, 0x04, 0x0d, 0x28, 0x17, + 0x02, 0x05, 0x04, 0x39, 0x04, 0x02, 0x01, 0x0e, 0x38, 0x03, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x1d, + 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, + 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, + 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2d, 0x50, 0x58, 0x40, + 0x2c, 0x0d, 0x06, 0x02, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, + 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, + 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x33, 0x00, 0x0d, 0x03, 0x04, 0x03, 0x0d, 0x04, 0x80, 0x06, + 0x01, 0x03, 0x07, 0x01, 0x04, 0x05, 0x03, 0x04, 0x69, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, + 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, + 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x29, 0x45, 0x45, 0x01, 0x00, 0x45, 0x48, 0x45, 0x48, 0x47, 0x46, 0x41, + 0x40, 0x3d, 0x3b, 0x37, 0x35, 0x32, 0x31, 0x30, 0x2f, 0x2c, 0x2a, 0x25, 0x23, 0x1f, 0x1e, 0x1b, 0x19, 0x14, 0x12, + 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x44, 0x01, 0x44, 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x07, 0x07, 0x33, 0x37, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, + 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, + 0x06, 0x06, 0x25, 0x13, 0x33, 0x03, 0x30, 0x13, 0x20, 0x0d, 0x0e, 0x1a, 0x10, 0x1e, 0x2d, 0x0d, 0x6e, 0x5d, 0x07, + 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0c, + 0x10, 0x2f, 0x46, 0x31, 0x1a, 0x35, 0x10, 0x18, 0x0e, 0x21, 0x13, 0x28, 0x2d, 0x0e, 0x0c, 0x74, 0x0e, 0x73, 0x70, + 0x12, 0x4b, 0x49, 0x26, 0x19, 0x0c, 0x1c, 0x10, 0x1e, 0x2c, 0x0d, 0x6e, 0xe7, 0x70, 0x12, 0x4c, 0x02, 0x82, 0xa1, + 0x58, 0xa2, 0xf0, 0x06, 0x04, 0x4a, 0x04, 0x07, 0x32, 0x40, 0x02, 0x0a, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, 0x0b, + 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x34, 0x44, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, + 0x43, 0xfd, 0xec, 0x53, 0x5e, 0x0a, 0x4a, 0x04, 0x07, 0x33, 0x3f, 0x02, 0x0a, 0xfd, 0xec, 0x53, 0x5e, 0xf0, 0x02, + 0xf8, 0xfd, 0x08, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4a, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0xff, 0x90, 0xff, 0x10, 0x02, 0x53, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x00, + 0x02, 0xf9, 0x02, 0xfd, 0x00, 0x2d, 0x00, 0x42, 0x40, 0x3f, 0x1d, 0x0c, 0x02, 0x02, 0x01, 0x1e, 0x0d, 0x02, 0x03, + 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, 0x00, 0x00, 0x03, + 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x2d, 0x2c, 0x2b, 0x11, 0x11, 0x13, 0x25, 0x24, 0x13, 0x25, 0x26, 0x11, 0x0c, 0x07, 0x1f, 0x2b, 0x33, 0x13, + 0x23, 0x3f, 0x02, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, + 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x23, + 0x13, 0x23, 0x03, 0x2b, 0x63, 0x5d, 0x07, 0x64, 0x0b, 0x10, 0x2f, 0x46, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, + 0x14, 0x27, 0x2d, 0x0e, 0x0c, 0xe7, 0x0b, 0x0f, 0x2f, 0x47, 0x31, 0x19, 0x35, 0x10, 0x17, 0x0e, 0x21, 0x14, 0x27, + 0x2d, 0x0e, 0x0c, 0x73, 0x0d, 0x73, 0x63, 0x58, 0x63, 0xe6, 0x63, 0x01, 0xd5, 0x25, 0x21, 0x30, 0x45, 0x4d, 0x20, + 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, 0x33, 0x33, 0x45, 0x4d, 0x20, 0x0b, 0x08, 0x43, 0x05, 0x09, 0x2c, 0x3e, + 0x33, 0x43, 0xfe, 0x2b, 0x01, 0xd5, 0xfe, 0x2b, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x03, 0x8a, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0x7c, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, + 0x03, 0x91, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0x7c, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x4c, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, + 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x53, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x3e, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf8, 0x01, 0x3e, 0x01, 0xb9, + 0x01, 0x07, 0x00, 0x68, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, 0x01, 0x0c, 0x01, 0xac, 0x01, 0x07, 0x00, 0x62, 0xff, 0xac, 0xfe, 0x61, + 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x61, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xef, 0x00, 0x00, 0x01, + 0x36, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x04, 0xff, 0xf9, 0x01, 0x3f, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x61, 0xff, + 0xb3, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x01, 0x3e, 0x01, 0xaf, 0x01, 0x07, 0x00, 0x64, 0xff, 0xb4, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, + 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0d, 0xff, 0xf9, 0x01, 0x46, 0x01, 0xad, 0x01, 0x07, + 0x00, 0x65, 0xff, 0xae, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x11, 0xff, 0xf9, 0x01, 0x44, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa7, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x5c, 0x01, + 0xac, 0x01, 0x07, 0x00, 0x66, 0xff, 0xae, 0xfe, 0x5f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x5f, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x01, 0x3b, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x67, 0xff, 0xa7, 0xfe, + 0x61, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x61, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x07, 0xff, 0xf9, + 0x01, 0x39, 0x01, 0xb3, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, + 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4a, 0x01, 0x17, 0x01, 0x7b, 0x02, 0xd8, 0x01, 0x07, 0x00, 0x68, + 0xff, 0xe5, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x75, 0x01, 0x1e, 0x01, 0x41, 0x02, 0xca, 0x01, 0x07, 0x00, 0x62, 0xff, 0xe1, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, + 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x2b, 0x01, 0x1f, 0x01, 0x72, 0x02, 0xd4, 0x01, + 0x07, 0x00, 0x60, 0xff, 0xe4, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x37, 0x01, 0x18, 0x01, 0x72, 0x02, 0xd5, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe6, 0xff, 0x7f, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x31, 0x01, 0x1f, 0x01, 0x70, + 0x02, 0xce, 0x01, 0x07, 0x00, 0x64, 0xff, 0xe6, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x45, 0x01, 0x18, 0x01, 0x7e, 0x02, 0xcc, 0x01, 0x07, 0x00, 0x65, 0xff, 0xe6, + 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x53, 0x01, + 0x18, 0x01, 0x86, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x5b, 0x01, 0x20, 0x01, 0x98, 0x02, 0xcc, 0x01, 0x07, 0x00, + 0x66, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x3b, 0x01, 0x18, 0x01, 0x77, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x67, 0xff, 0xe3, 0xff, 0x7f, 0x00, 0x09, 0xb1, + 0x00, 0x03, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x49, 0x01, 0x18, 0x01, 0x7b, 0x02, 0xd2, + 0x01, 0x07, 0x00, 0x6a, 0xff, 0xea, 0xff, 0x7f, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7f, 0xb0, 0x35, 0x2b, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8a, 0x01, 0x08, 0x00, 0x18, 0x00, 0x71, 0x00, 0x06, 0x00, 0x02, + 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x40, 0x01, 0xf5, 0x02, 0x87, 0x02, 0xa2, 0x02, 0xca, + 0x02, 0xf2, 0x03, 0x1f, 0x03, 0x47, 0x03, 0x67, 0x03, 0x83, 0x03, 0xa4, 0x03, 0xbf, 0x04, 0x09, 0x04, 0x32, 0x04, + 0x74, 0x04, 0xd8, 0x05, 0x18, 0x05, 0x6c, 0x05, 0xd7, 0x05, 0xfa, 0x06, 0x66, 0x06, 0xce, 0x07, 0x08, 0x07, 0x43, + 0x07, 0x59, 0x07, 0x84, 0x07, 0x9a, 0x07, 0xf5, 0x08, 0xaa, 0x08, 0xe2, 0x09, 0x3b, 0x09, 0x84, 0x09, 0xbc, 0x09, + 0xec, 0x0a, 0x17, 0x0a, 0x6a, 0x0a, 0x98, 0x0a, 0xc2, 0x0a, 0xf3, 0x0b, 0x23, 0x0b, 0x43, 0x0b, 0x81, 0x0b, 0xb6, + 0x0b, 0xfc, 0x0c, 0x36, 0x0c, 0x85, 0x0c, 0xc7, 0x0d, 0x21, 0x0d, 0x44, 0x0d, 0x80, 0x0d, 0xad, 0x0d, 0xfb, 0x0e, + 0x2a, 0x0e, 0x52, 0x0e, 0x7c, 0x0e, 0xa0, 0x0e, 0xba, 0x0e, 0xde, 0x0f, 0x05, 0x0f, 0x25, 0x0f, 0x4f, 0x0f, 0xbd, + 0x10, 0x42, 0x10, 0x8a, 0x11, 0x0e, 0x11, 0x6a, 0x11, 0xdf, 0x12, 0x69, 0x12, 0xc2, 0x13, 0x05, 0x13, 0x62, 0x13, + 0xa4, 0x13, 0xc9, 0x14, 0x3c, 0x14, 0x8e, 0x14, 0xd3, 0x15, 0x41, 0x15, 0xac, 0x15, 0xff, 0x16, 0x54, 0x16, 0xb4, + 0x17, 0x09, 0x17, 0x38, 0x17, 0x86, 0x17, 0xb2, 0x17, 0xfa, 0x18, 0x23, 0x18, 0x81, 0x18, 0xa6, 0x19, 0x02, 0x19, + 0x47, 0x19, 0x8a, 0x19, 0xeb, 0x1a, 0x12, 0x1a, 0x2d, 0x1a, 0x84, 0x1a, 0xd7, 0x1a, 0xfc, 0x1b, 0x5f, 0x1b, 0xa4, + 0x1c, 0x05, 0x1c, 0x64, 0x1c, 0xa7, 0x1d, 0x55, 0x1e, 0x53, 0x1f, 0x41, 0x1f, 0x4d, 0x1f, 0x59, 0x1f, 0xbf, 0x1f, + 0xcb, 0x1f, 0xd7, 0x1f, 0xe3, 0x1f, 0xef, 0x1f, 0xfe, 0x20, 0x0d, 0x20, 0x1c, 0x20, 0x2b, 0x20, 0x3a, 0x20, 0x49, + 0x20, 0x58, 0x20, 0x67, 0x20, 0x76, 0x20, 0x85, 0x20, 0x94, 0x20, 0xa3, 0x20, 0xb2, 0x20, 0xc1, 0x20, 0xd0, 0x20, + 0xdf, 0x20, 0xee, 0x20, 0xfd, 0x21, 0x0c, 0x21, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, + 0x57, 0x3e, 0x69, 0x66, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, + 0xa2, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x0f, 0xfd, 0x67, 0xfe, 0x7b, 0x0a, 0xcf, 0x04, 0x3c, 0x00, 0x02, + 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5e, 0x01, 0x04, 0x00, 0x00, 0x01, + 0x05, 0x00, 0x14, 0x01, 0x88, 0x00, 0x6d, 0x02, 0x86, 0x00, 0x1e, 0x02, 0x27, 0x00, 0x22, 0x03, 0x1f, 0x00, 0x50, + 0x02, 0xa1, 0x00, 0x20, 0x00, 0xdc, 0x00, 0x6d, 0x01, 0x22, 0x00, 0x28, 0x01, 0x22, 0xff, 0xb3, 0x02, 0x27, 0x00, + 0x67, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x00, 0xff, 0xd5, 0x01, 0x39, 0x00, 0x1a, 0x01, 0x00, 0x00, 0x14, 0x01, 0x64, + 0xff, 0xd2, 0x02, 0x27, 0x00, 0x39, 0x02, 0x27, 0x00, 0x8f, 0x02, 0x27, 0x00, 0x03, 0x02, 0x27, 0x00, 0x16, 0x02, + 0x27, 0x00, 0x06, 0x02, 0x27, 0x00, 0x25, 0x02, 0x27, 0x00, 0x3f, 0x02, 0x27, 0x00, 0x51, 0x02, 0x27, 0x00, 0x2d, + 0x02, 0x27, 0x00, 0x2f, 0x01, 0x00, 0x00, 0x14, 0x01, 0x00, 0xff, 0xcf, 0x02, 0x3c, 0x00, 0x46, 0x02, 0x3c, 0x00, + 0x4c, 0x02, 0x3c, 0x00, 0x46, 0x01, 0xae, 0x00, 0x4d, 0x03, 0x50, 0x00, 0x35, 0x02, 0x32, 0xff, 0xc7, 0x02, 0x58, + 0x00, 0x29, 0x02, 0x4b, 0x00, 0x48, 0x02, 0x9b, 0x00, 0x29, 0x02, 0x02, 0x00, 0x29, 0x01, 0xdd, 0x00, 0x29, 0x02, + 0xa6, 0x00, 0x48, 0x02, 0xa8, 0x00, 0x2a, 0x01, 0x44, 0xff, 0xec, 0x01, 0x11, 0xff, 0x64, 0x02, 0x32, 0x00, 0x29, + 0x01, 0xde, 0x00, 0x29, 0x03, 0x49, 0x00, 0x28, 0x02, 0xc3, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x37, 0x00, + 0x29, 0x02, 0xd1, 0x00, 0x48, 0x02, 0x3d, 0x00, 0x29, 0x01, 0xf9, 0x00, 0x13, 0x01, 0xf5, 0x00, 0x5a, 0x02, 0xa5, + 0x00, 0x4f, 0x02, 0x28, 0x00, 0x5c, 0x03, 0x58, 0x00, 0x6b, 0x02, 0x0f, 0xff, 0xcc, 0x01, 0xfd, 0x00, 0x5c, 0x02, + 0x13, 0xff, 0xf6, 0x01, 0x22, 0xff, 0xf7, 0x01, 0x64, 0x00, 0x6c, 0x01, 0x22, 0xff, 0xb8, 0x02, 0x3c, 0x00, 0x26, + 0x01, 0x8b, 0xff, 0xa4, 0x01, 0x16, 0x00, 0x92, 0x02, 0x38, 0x00, 0x30, 0x02, 0x43, 0x00, 0x1c, 0x01, 0xc5, 0x00, + 0x30, 0x02, 0x43, 0x00, 0x30, 0x01, 0xf3, 0x00, 0x30, 0x01, 0x3e, 0xff, 0x90, 0x02, 0x43, 0x00, 0x19, 0x02, 0x43, + 0x00, 0x1c, 0x01, 0x02, 0x00, 0x1c, 0x01, 0x02, 0xff, 0x82, 0x01, 0xef, 0x00, 0x1b, 0x01, 0x02, 0x00, 0x1b, 0x03, + 0x6b, 0x00, 0x1c, 0x02, 0x43, 0x00, 0x18, 0x02, 0x33, 0x00, 0x30, 0x02, 0x43, 0xff, 0xea, 0x02, 0x43, 0x00, 0x30, + 0x01, 0x8e, 0x00, 0x1c, 0x01, 0xb0, 0x00, 0x05, 0x01, 0x4c, 0x00, 0x2c, 0x02, 0x43, 0x00, 0x37, 0x01, 0xd3, 0x00, + 0x30, 0x02, 0xd3, 0x00, 0x39, 0x01, 0xe3, 0xff, 0xdb, 0x01, 0xd3, 0xff, 0xa2, 0x01, 0xbd, 0xff, 0xf1, 0x01, 0x5e, + 0x00, 0x0b, 0x02, 0x27, 0x01, 0x04, 0x01, 0x5e, 0xff, 0xdb, 0x02, 0x3c, 0x00, 0x46, 0x01, 0x61, 0x00, 0x47, 0x01, + 0x61, 0x00, 0x51, 0x01, 0x61, 0x00, 0x94, 0x00, 0x82, 0xff, 0x10, 0x01, 0x61, 0x00, 0x4b, 0x01, 0x61, 0x00, 0x5f, + 0x01, 0x61, 0x00, 0x71, 0x01, 0x61, 0x00, 0x58, 0x01, 0x61, 0x00, 0x65, 0x01, 0x61, 0x00, 0x6a, 0x01, 0x61, 0x00, + 0x5f, 0x01, 0x3e, 0x00, 0x2b, 0x02, 0x7e, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, 0x03, 0x80, 0xff, 0x90, 0x02, 0x40, + 0xff, 0x90, 0x02, 0x40, 0xff, 0x90, 0x02, 0x7c, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x03, 0x7e, 0x00, 0x2b, 0x02, + 0x40, 0x00, 0x2b, 0x02, 0x40, 0x00, 0x2b, 0x01, 0x61, 0x00, 0x0d, 0x00, 0x40, 0xff, 0xef, 0x00, 0x04, 0xff, 0xff, + 0x00, 0x0d, 0x00, 0x11, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x07, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x2b, 0x00, 0x37, 0x00, + 0x31, 0x00, 0x45, 0x00, 0x53, 0x00, 0x5b, 0x00, 0x3b, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, + 0xfe, 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x67, 0xfd, 0x67, 0x0a, 0xcf, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x26, 0x01, 0x90, 0x00, 0x05, + 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, + 0x32, 0x01, 0x42, 0x00, 0x00, 0x02, 0x0b, 0x05, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0x81, 0x00, + 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x18, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, + 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, + 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, + 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, + 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, + 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, + 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, + 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, + 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, + 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, + 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, + 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, + 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, + 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, + 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, + 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, + 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, + 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, + 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, + 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, + 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, + 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, + 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, + 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, + 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, + 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, + 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, + 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, + 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, + 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, + 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, + 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, + 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, + 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, + 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, + 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, + 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, + 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, + 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, + 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, + 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, + 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, + 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, + 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, + 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, + 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, + 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, + 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, + 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, + 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, + 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, + 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, + 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, + 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, + 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, + 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, + 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, + 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, + 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, + 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, + 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, + 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, + 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, + 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, + 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, + 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, + 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, + 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, + 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, + 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, + 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, + 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, + 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, + 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, + 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, + 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, + 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, + 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, + 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, + 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, + 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, + 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, + 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, + 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, + 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, + 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, + 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, + 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, + 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, + 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, + 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, + 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, + 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, + 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, + 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, + 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, + 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, + 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, + 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, + 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, + 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, + 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, + 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, + 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, + 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, + 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, + 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, + 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, + 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, + 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, + 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, + 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, + 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, + 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, + 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, + 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, + 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, + 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, + 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, + 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, + 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, + 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, + 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, + 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, + 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, + 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, + 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, + 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, + 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, + 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, + 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, + 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, + 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, + 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, + 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, + 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, + 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, + 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, + 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, + 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, + 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, + 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, + 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, + 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, + 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, + 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, + 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, + 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, + 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, + 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, + 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, + 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, + 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, + 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, + 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, + 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, + 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, + 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, + 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, + 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, + 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, + 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, + 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, + 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, + 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, + 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, + 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, + 0x02, 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, + 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, + 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, + 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, + 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, + 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, + 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, + 0x06, 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, + 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x48, 0x02, 0xca, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0xff, + 0x10, 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x20, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, + 0x02, 0x3b, 0x02, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x02, 0x47, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x59, 0x00, + 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x18, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, + 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x21, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x4c, 0x00, 0x4c, 0x02, + 0x3b, 0x00, 0x00, 0x02, 0x44, 0xff, 0xf8, 0x00, 0x45, 0x00, 0x45, 0x00, 0x3e, 0x00, 0x3e, 0x01, 0x68, 0x00, 0xe8, + 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x45, 0x00, 0x45, 0x00, 0x3e, 0x00, + 0x3e, 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x59, 0x00, 0x59, 0x00, 0x49, 0x00, 0x49, 0x02, 0xca, 0x00, 0x00, 0x02, 0xec, + 0x02, 0x18, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xec, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x00, + 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, 0x2c, 0x01, 0x2b, 0xff, 0x7e, 0x01, 0x61, 0x00, 0xe2, 0xff, 0xa0, 0xff, 0x10, + 0x01, 0x34, 0xff, 0x77, 0x01, 0x61, 0x00, 0xe8, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x2c, 0x00, + 0x2c, 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe0, 0x02, 0x61, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe0, 0x01, 0x98, 0x02, 0xe0, + 0x02, 0x67, 0x01, 0x19, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, + 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, + 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0c, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, + 0x34, 0x00, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x20, 0x01, 0x08, 0x00, 0x03, 0x00, 0x01, + 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x28, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1e, 0x01, + 0x7c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, + 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, + 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, + 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, + 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, + 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, + 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, + 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, + 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, + 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, + 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, + 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, + 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, + 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, + 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, + 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, + 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, + 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, + 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, + 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, + 0x00, 0xff, 0x9c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, + 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, + 0x0a, 0x00, 0x22, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, 0x00, 0x4a, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x3c, 0x00, 0x4a, + 0x00, 0x4a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, + 0xfa, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0xf7, + 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xf9, 0x00, 0x01, 0x02, 0x2d, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x01, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, + 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, + 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, + 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, 0x00, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, 0x00, + 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, 0xe4, + 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, + 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, + 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, + 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, 0xc4, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, 0x00, + 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, + 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, 0x00, + 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, + 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, + 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, + 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, 0x03, + 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, 0xe2, + 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, + 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, 0xe2, + 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, + 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0xff, + 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, 0x2d, + 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, + 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, 0x53, + 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, 0x0d, + 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, 0x00, + 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, 0x2c, + 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, + 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x05, + 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, 0x00, + 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, 0x47, + 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, + 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x0d, + 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, 0x00, + 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, 0x28, + 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, 0x00, + 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x08, + 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, 0x00, + 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, 0x4e, + 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, 0x00, + 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, 0x55, + 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, 0x00, + 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, + 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, + 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, + 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, 0x00, + 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, 0x4a, + 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, + 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, 0x00, + 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, 0x03, + 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, 0x00, + 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, + 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, 0x00, + 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, 0x6b, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; + + constexpr unsigned char BOLD_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x06, 0x75, 0x08, + 0xc3, 0x00, 0x00, 0x4f, 0x3c, 0x00, 0x00, 0x00, 0x6c, 0x47, 0x50, 0x4f, 0x53, 0x28, 0x98, 0x0a, 0xef, 0x00, 0x00, + 0x4f, 0xa8, 0x00, 0x00, 0x07, 0xb2, 0x47, 0x53, 0x55, 0x42, 0x39, 0x7a, 0x34, 0x30, 0x00, 0x00, 0x57, 0x5c, 0x00, + 0x00, 0x01, 0x50, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x81, 0x61, 0x8b, 0x00, 0x00, 0x3c, 0x5c, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x3c, 0xbc, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x41, 0xb6, 0x1e, 0xcf, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x3c, 0xf0, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x4f, 0x34, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xea, 0xe8, 0x66, 0x13, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x37, 0xca, 0x68, 0x65, 0x61, 0x64, 0x28, 0x6e, 0xdc, 0x4a, 0x00, 0x00, 0x3a, 0x14, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0c, 0x9d, 0x0b, 0xd8, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xf4, 0x22, 0x11, 0xe6, 0x00, 0x00, 0x3a, 0x4c, 0x00, 0x00, 0x01, 0xea, 0x6c, 0x6f, 0x63, 0x61, 0x08, + 0xbe, 0xfb, 0x1b, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x01, 0x0a, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x55, 0x10, 0x44, + 0x00, 0x00, 0x38, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x27, 0x83, 0x40, 0x7b, 0x00, 0x00, 0x4d, + 0x30, 0x00, 0x00, 0x01, 0xe4, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x9f, 0x00, 0x32, 0x00, 0x00, 0x4f, 0x14, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0x44, 0x7e, 0xc6, 0xb9, 0x00, 0x00, 0x4a, 0xfc, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, + 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, + 0x24, 0x23, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x37, 0x23, 0x03, 0x33, 0x03, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0xc9, 0x78, 0x19, 0xaa, 0xac, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0xe8, + 0x01, 0xe2, 0xfd, 0x7c, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x3d, 0x01, 0xc8, 0x01, 0xa1, + 0x02, 0xca, 0x00, 0x03, 0x00, 0x07, 0x00, 0x24, 0x40, 0x21, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x05, 0x03, 0x04, + 0x03, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, + 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0x21, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x01, + 0x64, 0x14, 0x67, 0x14, 0x02, 0xca, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x16, + 0x00, 0x00, 0x02, 0x70, 0x02, 0xc9, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x0a, 0x02, 0x08, 0x0f, + 0x10, 0x0d, 0x03, 0x07, 0x00, 0x08, 0x07, 0x68, 0x0e, 0x06, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, 0x02, 0x00, 0x01, + 0x67, 0x0b, 0x01, 0x09, 0x09, 0x6a, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, + 0x1c, 0x00, 0x1b, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x0d, 0x1f, 0x2b, 0x01, 0x07, 0x33, 0x15, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x23, 0x37, + 0x23, 0x35, 0x33, 0x37, 0x23, 0x35, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, 0x15, 0x05, 0x33, 0x37, + 0x23, 0x01, 0xe8, 0x17, 0x7e, 0x91, 0x26, 0x6b, 0x26, 0x5f, 0x25, 0x69, 0x24, 0x74, 0x87, 0x17, 0x7b, 0x8d, 0x26, + 0x6b, 0x26, 0x61, 0x26, 0x69, 0x26, 0x75, 0xfe, 0x97, 0x60, 0x17, 0x60, 0x01, 0x9c, 0x71, 0x65, 0xc6, 0xc6, 0xc6, + 0xc6, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, 0x71, 0x00, 0x00, 0x03, 0x00, 0x2b, 0xff, 0xc6, 0x02, + 0x15, 0x02, 0xf7, 0x00, 0x22, 0x00, 0x28, 0x00, 0x2e, 0x00, 0x3f, 0x40, 0x3c, 0x2e, 0x29, 0x28, 0x23, 0x19, 0x18, + 0x15, 0x14, 0x08, 0x04, 0x0a, 0x01, 0x03, 0x20, 0x03, 0x02, 0x00, 0x01, 0x02, 0x4c, 0x0f, 0x01, 0x03, 0x01, 0x4b, + 0x00, 0x03, 0x02, 0x01, 0x02, 0x03, 0x01, 0x80, 0x00, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x69, 0x00, 0x04, 0x04, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6c, 0x04, 0x4e, 0x1e, 0x11, 0x19, 0x15, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x37, 0x26, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x35, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x37, 0x35, 0x33, 0x15, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x27, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x15, 0x23, 0x11, 0x06, 0x15, 0x14, 0x16, 0x17, 0x13, + 0x36, 0x35, 0x34, 0x26, 0x27, 0xfd, 0x41, 0x66, 0x2a, 0x29, 0x74, 0x34, 0x4d, 0x5d, 0x28, 0x75, 0x5d, 0x43, 0x6f, + 0x5b, 0x2e, 0x28, 0x51, 0x23, 0x36, 0x62, 0x3d, 0x6a, 0x6b, 0x43, 0x3f, 0x1e, 0x21, 0x43, 0x42, 0x21, 0x21, 0x28, + 0x02, 0x15, 0x13, 0x81, 0x14, 0x21, 0x03, 0x97, 0x1e, 0x39, 0x46, 0x31, 0x4b, 0x59, 0x08, 0x4b, 0x49, 0x04, 0x29, + 0x72, 0x11, 0x12, 0x03, 0x90, 0x14, 0x2f, 0x48, 0x3b, 0x49, 0x62, 0x0a, 0x64, 0x02, 0x6d, 0x09, 0x2a, 0x15, 0x1c, + 0x0f, 0xfe, 0xde, 0x0c, 0x2e, 0x14, 0x1d, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x1e, 0xff, 0xf7, 0x03, 0x68, 0x02, 0xd4, + 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x33, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x2c, + 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0c, + 0x01, 0x04, 0x04, 0x00, 0x61, 0x0b, 0x03, 0x0a, 0x03, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, + 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x0d, 0x01, 0x06, 0x0e, 0x01, + 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, + 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x07, 0x01, + 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x34, 0x0d, 0x01, 0x06, 0x0e, 0x01, 0x08, 0x01, 0x06, 0x08, 0x6a, 0x00, + 0x05, 0x00, 0x01, 0x09, 0x05, 0x01, 0x69, 0x0b, 0x01, 0x03, 0x03, 0x6a, 0x4d, 0x0c, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x0a, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x09, 0x09, 0x07, 0x61, 0x00, 0x07, 0x07, + 0x71, 0x07, 0x4e, 0x59, 0x59, 0x40, 0x2b, 0x29, 0x28, 0x1d, 0x1c, 0x11, 0x10, 0x0c, 0x0c, 0x01, 0x00, 0x2f, 0x2d, + 0x28, 0x33, 0x29, 0x33, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x17, 0x15, 0x10, 0x1b, 0x11, 0x1b, 0x0c, 0x0f, 0x0c, + 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x05, 0x01, 0x23, 0x01, 0x05, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x05, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0xc6, 0x50, 0x5c, 0x56, 0x56, 0x4e, 0x5a, 0x55, 0x02, 0x50, 0xfe, + 0x74, 0x77, 0x01, 0x8c, 0xfe, 0x7b, 0x1b, 0x18, 0x18, 0x1b, 0x1c, 0x19, 0x19, 0x01, 0xd9, 0x4f, 0x5d, 0x57, 0x55, + 0x4e, 0x5a, 0x55, 0x54, 0x1c, 0x17, 0x17, 0x1c, 0x1c, 0x19, 0x19, 0x02, 0xd4, 0x75, 0x6a, 0x6a, 0x77, 0x77, 0x6a, + 0x6a, 0x75, 0x0a, 0xfd, 0x36, 0x02, 0xca, 0x57, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3d, 0x42, 0xbc, 0x75, 0x6a, + 0x6a, 0x77, 0x77, 0x6a, 0x6a, 0x75, 0x61, 0x42, 0x3d, 0x3d, 0x43, 0x42, 0x3e, 0x3e, 0x41, 0x00, 0x00, 0x03, 0x00, + 0x28, 0xff, 0xf6, 0x02, 0xee, 0x02, 0xd4, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x37, 0x00, 0x7d, 0x40, 0x12, 0x28, 0x1b, + 0x02, 0x01, 0x04, 0x37, 0x0f, 0x08, 0x07, 0x04, 0x05, 0x01, 0x12, 0x01, 0x02, 0x05, 0x03, 0x4c, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x23, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, + 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x02, 0x61, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x40, 0x21, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x01, 0x01, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6b, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, + 0x40, 0x17, 0x23, 0x22, 0x01, 0x00, 0x35, 0x33, 0x22, 0x2d, 0x23, 0x2d, 0x16, 0x14, 0x11, 0x10, 0x0c, 0x0b, 0x00, + 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, + 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, 0x27, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x01, 0x36, 0x3a, 0x5a, 0x34, 0x52, 0x3d, 0x8b, 0x14, 0x1e, 0x0a, 0x9b, 0x0f, + 0x3a, 0x2d, 0x93, 0xb8, 0x38, 0x2b, 0x6a, 0x3e, 0x7a, 0x89, 0x46, 0x3d, 0x27, 0x1f, 0x35, 0x5f, 0x3c, 0x19, 0x2d, + 0x19, 0x15, 0x2a, 0x2d, 0x28, 0x4a, 0x1c, 0x21, 0x40, 0x30, 0x20, 0x38, 0x17, 0x02, 0xd4, 0x24, 0x45, 0x32, 0x45, + 0x5e, 0x23, 0x87, 0x22, 0x4b, 0x26, 0x38, 0x80, 0x38, 0x8f, 0x37, 0x1e, 0x23, 0x70, 0x5b, 0x4c, 0x5b, 0x23, 0x2d, + 0x4c, 0x2b, 0x33, 0x4a, 0x28, 0x73, 0x19, 0x23, 0x19, 0x2e, 0x18, 0x17, 0x2e, 0x1e, 0x1e, 0x1a, 0xfe, 0xd1, 0x15, + 0x2f, 0x1f, 0x2b, 0x31, 0x10, 0x0e, 0x00, 0x01, 0x00, 0x3d, 0x01, 0xc8, 0x00, 0xcd, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x03, 0x23, 0x03, 0xcd, 0x14, 0x68, 0x14, 0x02, 0xca, 0xfe, 0xfe, + 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, 0x62, 0x01, 0x35, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, + 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x13, 0x34, + 0x36, 0x37, 0x33, 0x06, 0x06, 0x15, 0x14, 0x16, 0x17, 0x23, 0x26, 0x26, 0x28, 0x47, 0x4c, 0x7a, 0x44, 0x47, 0x47, + 0x43, 0x79, 0x4c, 0x47, 0x01, 0x12, 0x7a, 0xe3, 0x5b, 0x5e, 0xe2, 0x77, 0x74, 0xe1, 0x5c, 0x58, 0xdf, 0x00, 0x00, + 0x01, 0x00, 0x1e, 0xff, 0x62, 0x01, 0x2b, 0x02, 0xca, 0x00, 0x0d, 0x00, 0x13, 0x40, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x00, 0x4e, 0x16, 0x13, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x14, 0x06, 0x07, 0x23, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x01, 0x2b, 0x47, 0x4c, 0x79, 0x44, 0x46, 0x47, 0x44, 0x7a, 0x4c, + 0x47, 0x01, 0x12, 0x79, 0xdf, 0x58, 0x5c, 0xe1, 0x74, 0x77, 0xe2, 0x5e, 0x5b, 0xe3, 0x00, 0x01, 0x00, 0x1d, 0x01, + 0x24, 0x02, 0x01, 0x02, 0xf8, 0x00, 0x0e, 0x00, 0x23, 0x40, 0x20, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x0d, 0x00, 0x49, 0x01, 0x01, 0x00, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x0e, 0x02, 0x0d, 0x16, 0x2b, 0x01, 0x07, 0x37, 0x17, 0x07, 0x17, 0x07, 0x27, 0x07, 0x27, 0x37, 0x27, 0x37, + 0x17, 0x27, 0x01, 0x4f, 0x14, 0xb5, 0x11, 0xa5, 0x6c, 0x6f, 0x4c, 0x43, 0x74, 0x6c, 0xa5, 0x13, 0xb2, 0x14, 0x02, + 0xf8, 0xb4, 0x33, 0x7c, 0x0c, 0x90, 0x3b, 0x98, 0x98, 0x3b, 0x90, 0x0e, 0x7a, 0x33, 0xb4, 0x00, 0x01, 0x00, 0x2b, + 0x00, 0x6f, 0x02, 0x10, 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, + 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, + 0x33, 0x35, 0x33, 0x01, 0x53, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, + 0x00, 0x01, 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe0, 0x00, 0x74, 0x00, 0x08, 0x00, 0x18, 0x40, 0x15, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x13, 0x13, 0x02, 0x0d, 0x18, 0x2b, + 0x37, 0x06, 0x06, 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0xe0, 0x0d, 0x30, 0x19, 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x69, + 0x35, 0x7e, 0x37, 0x3b, 0x86, 0x34, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0xce, 0x01, 0x23, 0x01, 0x4a, 0x00, 0x03, + 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x35, 0x21, 0x15, 0x1c, 0x01, + 0x07, 0xce, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x00, 0x9a, 0x00, 0x0b, 0x00, 0x13, 0x40, + 0x10, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x22, 0x02, 0x0d, 0x18, 0x2b, 0x37, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, + 0x33, 0x46, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x01, 0x00, 0x07, 0xff, 0xfa, 0x01, 0x9a, 0x02, 0xd0, + 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x9a, 0xfe, 0xf6, 0x89, + 0x01, 0x0a, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x02, 0x00, 0x24, 0xff, 0xf6, 0x02, 0x17, 0x02, 0xd5, 0x00, + 0x0d, 0x00, 0x19, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, + 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x24, 0x25, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0x17, 0x31, 0x6d, 0x5c, 0x81, 0x78, 0x30, 0x6e, 0x5b, 0x80, 0x7a, 0xfe, 0xa3, + 0x2a, 0x39, 0x38, 0x2c, 0x2c, 0x38, 0x39, 0x2a, 0x01, 0x65, 0x73, 0xa4, 0x58, 0xc3, 0xac, 0x74, 0xa4, 0x58, 0xc2, + 0xae, 0x7a, 0x7b, 0x7a, 0x7b, 0x7a, 0x7c, 0x7c, 0x00, 0x01, 0x00, 0x3b, 0x00, 0x00, 0x01, 0x9d, 0x02, 0xca, 0x00, + 0x0c, 0x00, 0x1b, 0x40, 0x18, 0x0a, 0x09, 0x05, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1a, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x21, 0x23, 0x11, 0x34, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x33, 0x01, 0x9d, 0x97, 0x03, 0x01, 0x05, 0x21, 0x0e, 0x52, 0x49, 0xe6, 0x7c, 0x01, 0x9d, + 0x1a, 0x54, 0x20, 0x06, 0x1f, 0x0c, 0x42, 0x5b, 0xb7, 0x00, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x1b, 0x02, + 0xd4, 0x00, 0x1d, 0x00, 0x2d, 0x40, 0x2a, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, + 0x03, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, + 0x00, 0x6b, 0x00, 0x4e, 0x28, 0x26, 0x28, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x3e, 0x02, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x15, 0x21, 0x02, 0x1b, 0xfe, 0x0d, 0xb3, 0x36, 0x42, 0x1e, 0x2f, 0x28, 0x29, 0x4e, 0x2b, 0x52, 0x1f, 0x45, 0x5b, + 0x40, 0x46, 0x65, 0x37, 0x2f, 0x59, 0x3f, 0x5c, 0x01, 0x37, 0x69, 0xb5, 0x38, 0x4b, 0x3d, 0x23, 0x2b, 0x2a, 0x26, + 0x23, 0x61, 0x1b, 0x2e, 0x1d, 0x33, 0x57, 0x37, 0x3b, 0x62, 0x60, 0x3a, 0x56, 0x07, 0x00, 0x00, 0x01, 0x00, 0x26, + 0xff, 0xf6, 0x02, 0x14, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x3f, 0x40, 0x3c, 0x26, 0x01, 0x04, 0x05, 0x25, 0x01, 0x03, + 0x04, 0x03, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x0d, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x25, 0x25, 0x21, 0x25, 0x24, 0x2a, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x14, 0x06, + 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x26, 0x23, 0x23, 0x35, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x01, 0xff, 0x59, 0x41, 0x56, 0x59, 0x3d, 0x7f, 0x64, 0x74, 0x5a, 0x2e, 0x65, 0x2b, 0x51, 0x41, + 0x1e, 0x4b, 0x43, 0x36, 0x37, 0x42, 0x45, 0x19, 0x2f, 0x37, 0x33, 0x4b, 0x1a, 0x46, 0x2a, 0x71, 0x4e, 0x6e, 0x81, + 0x02, 0x2a, 0x4a, 0x58, 0x10, 0x03, 0x0a, 0x54, 0x47, 0x3e, 0x63, 0x39, 0x27, 0x80, 0x17, 0x18, 0x38, 0x33, 0x1e, + 0x29, 0x15, 0x74, 0x19, 0x2b, 0x1c, 0x26, 0x2b, 0x23, 0x11, 0x68, 0x1e, 0x28, 0x59, 0x00, 0x00, 0x02, 0x00, 0x11, + 0x00, 0x00, 0x02, 0x2b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x27, 0x40, 0x24, 0x06, 0x01, 0x00, 0x04, 0x01, + 0x4c, 0x05, 0x01, 0x04, 0x02, 0x01, 0x00, 0x01, 0x04, 0x00, 0x67, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x1a, 0x11, 0x12, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x25, 0x23, 0x15, 0x23, 0x35, 0x21, + 0x35, 0x01, 0x33, 0x11, 0x33, 0x27, 0x34, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x07, 0x07, 0x33, 0x02, 0x2b, 0x56, + 0x93, 0xfe, 0xcf, 0x01, 0x39, 0x8b, 0x56, 0xe9, 0x02, 0x03, 0x01, 0x04, 0x09, 0x14, 0x0e, 0x83, 0xac, 0x94, 0x94, + 0x94, 0x69, 0x01, 0xcd, 0xfe, 0x3f, 0x79, 0x17, 0x42, 0x39, 0x09, 0x14, 0x26, 0x14, 0xc6, 0x00, 0x01, 0x00, 0x31, + 0xff, 0xf6, 0x02, 0x0e, 0x02, 0xca, 0x00, 0x1e, 0x00, 0x44, 0x40, 0x41, 0x1c, 0x17, 0x02, 0x03, 0x00, 0x16, 0x0b, + 0x02, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x03, 0x69, 0x00, + 0x05, 0x05, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, + 0x4e, 0x01, 0x00, 0x1b, 0x1a, 0x19, 0x18, 0x14, 0x12, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, + 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x15, 0x23, 0x07, 0x36, 0x36, 0x01, 0x2c, 0x41, 0x66, 0x3b, + 0x90, 0x8d, 0x38, 0x63, 0x25, 0x25, 0x68, 0x2e, 0x43, 0x47, 0x8f, 0x1c, 0x3c, 0x14, 0x3c, 0x1b, 0x01, 0x83, 0xff, + 0x0d, 0x11, 0x27, 0x01, 0xc8, 0x32, 0x60, 0x47, 0x74, 0x85, 0x14, 0x13, 0x82, 0x13, 0x1b, 0x37, 0x3a, 0x6c, 0x0b, + 0x05, 0x20, 0x01, 0x6c, 0x80, 0x8c, 0x03, 0x07, 0x00, 0x02, 0x00, 0x23, 0xff, 0xf6, 0x02, 0x1b, 0x02, 0xd2, 0x00, + 0x1e, 0x00, 0x2c, 0x00, 0x69, 0x40, 0x0e, 0x09, 0x01, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x11, 0x01, 0x05, 0x02, + 0x03, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, + 0x4e, 0x1b, 0x40, 0x1e, 0x00, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x69, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x70, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x20, + 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, 0x07, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x3e, 0x03, + 0x33, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x23, 0x22, 0x26, 0x26, 0x05, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, + 0x16, 0x23, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, 0x13, 0x2d, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x14, + 0x4b, 0x3c, 0x5e, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0x01, 0x02, 0x2c, 0x38, 0x30, 0x31, 0x21, 0x32, 0x1c, 0x18, + 0x31, 0x01, 0x2f, 0x3e, 0x78, 0x6b, 0x53, 0x2f, 0x03, 0x04, 0x79, 0x05, 0x05, 0x38, 0x65, 0x42, 0x23, 0x30, 0x76, + 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3d, 0x40, 0x34, 0x3c, 0x1d, 0x2e, 0x18, 0x21, 0x3f, 0x2a, 0x00, 0x01, 0x00, + 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x06, 0x00, 0x25, 0x40, 0x22, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, + 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x6f, 0x01, + 0x0c, 0xfe, 0xa0, 0x02, 0x00, 0xfe, 0xf2, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, 0x00, 0x23, 0xff, + 0xf6, 0x02, 0x18, 0x02, 0xd3, 0x00, 0x1b, 0x00, 0x27, 0x00, 0x35, 0x00, 0x36, 0x40, 0x33, 0x33, 0x22, 0x15, 0x07, + 0x04, 0x03, 0x02, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x70, 0x4d, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x2c, 0x2a, 0x1c, 0x27, 0x1d, 0x27, + 0x10, 0x0e, 0x00, 0x1b, 0x01, 0x1b, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x1e, + 0x02, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x17, + 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x36, 0x36, 0x35, 0x34, 0x26, 0x03, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x26, 0x27, 0x27, 0x06, 0x06, 0x01, 0x1e, 0x3e, 0x67, 0x3f, 0x49, 0x37, 0x26, 0x45, 0x2b, 0x3f, 0x71, 0x4a, + 0x78, 0x83, 0x50, 0x39, 0x30, 0x43, 0x40, 0x69, 0x3b, 0x25, 0x31, 0x34, 0x23, 0x22, 0x34, 0x31, 0x94, 0x37, 0x36, + 0x38, 0x38, 0x20, 0x2f, 0x19, 0x0d, 0x2e, 0x3a, 0x02, 0xd3, 0x26, 0x4c, 0x3a, 0x40, 0x53, 0x1b, 0x14, 0x35, 0x47, + 0x30, 0x3b, 0x58, 0x30, 0x66, 0x59, 0x4a, 0x5a, 0x1c, 0x1e, 0x55, 0x40, 0x39, 0x4c, 0x26, 0x6e, 0x26, 0x23, 0x25, + 0x2e, 0x11, 0x10, 0x2d, 0x27, 0x23, 0x26, 0xfe, 0x59, 0x27, 0x32, 0x30, 0x28, 0x1b, 0x29, 0x21, 0x0e, 0x07, 0x16, + 0x3a, 0x00, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x18, 0x02, 0xd2, 0x00, 0x1e, 0x00, 0x2c, 0x00, 0x3e, 0x40, + 0x3b, 0x11, 0x01, 0x02, 0x05, 0x0a, 0x01, 0x01, 0x02, 0x09, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, + 0x01, 0x05, 0x02, 0x69, 0x06, 0x01, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x20, 0x1f, 0x26, 0x24, 0x1f, 0x2c, 0x20, 0x2c, 0x24, 0x26, 0x24, 0x35, + 0x07, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x0e, 0x03, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, + 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x25, 0x22, 0x06, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x26, 0x02, 0x18, 0x12, 0x2d, 0x51, 0x7d, 0x59, 0x15, 0x38, 0x13, + 0x14, 0x2c, 0x16, 0x59, 0x61, 0x28, 0x03, 0x06, 0x15, 0x45, 0x44, 0x5b, 0x6e, 0x83, 0x70, 0x49, 0x76, 0x46, 0xfe, + 0xfe, 0x2c, 0x38, 0x30, 0x31, 0x22, 0x31, 0x1c, 0x18, 0x30, 0x01, 0x99, 0x3d, 0x79, 0x6b, 0x53, 0x2f, 0x03, 0x04, + 0x79, 0x04, 0x06, 0x39, 0x64, 0x42, 0x23, 0x30, 0x76, 0x6c, 0x74, 0x84, 0x43, 0x8b, 0x55, 0x3c, 0x41, 0x34, 0x3c, + 0x1e, 0x2d, 0x18, 0x21, 0x40, 0x29, 0x00, 0x02, 0x00, 0x36, 0xff, 0xf3, 0x00, 0xe3, 0x02, 0x2c, 0x00, 0x0b, 0x00, + 0x17, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x11, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, + 0x26, 0x36, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x33, 0x24, 0x23, 0x33, 0x33, 0x23, 0x24, 0x33, 0x01, + 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2d, 0x27, 0x27, 0xfe, 0x9a, 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, + 0x00, 0x1f, 0xff, 0x7f, 0x00, 0xe4, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, + 0x02, 0x03, 0x02, 0x63, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x01, 0x4e, 0x13, 0x15, 0x24, 0x22, + 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x13, 0x06, 0x06, + 0x07, 0x23, 0x36, 0x36, 0x37, 0x33, 0x39, 0x32, 0x24, 0x23, 0x32, 0x32, 0x23, 0x24, 0x32, 0xa7, 0x0d, 0x30, 0x19, + 0x6b, 0x0e, 0x1c, 0x07, 0x89, 0x01, 0xd9, 0x2e, 0x25, 0x25, 0x2e, 0x2c, 0x27, 0x27, 0xfe, 0xbc, 0x35, 0x7e, 0x37, + 0x3b, 0x86, 0x34, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, + 0x00, 0x01, 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x10, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, + 0x01, 0x4e, 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x2b, 0x00, 0xcc, 0x02, 0x10, 0x01, 0xf4, + 0x00, 0x03, 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, + 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, + 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, + 0x05, 0x35, 0x21, 0x15, 0x2b, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, + 0x00, 0x01, 0x00, 0x2b, 0x00, 0x63, 0x02, 0x10, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, + 0x2b, 0x37, 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x2b, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, + 0x9b, 0x75, 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x05, 0xff, 0xf3, 0x01, 0xc8, 0x02, 0xd4, 0x00, 0x1d, 0x00, + 0x29, 0x00, 0x32, 0x40, 0x2f, 0x0e, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x02, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x04, 0x61, + 0x00, 0x04, 0x04, 0x71, 0x04, 0x4e, 0x24, 0x23, 0x1a, 0x25, 0x29, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x34, 0x36, 0x37, + 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x0e, 0x02, 0x15, 0x15, 0x23, 0x07, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x8e, 0x24, + 0x33, 0x24, 0x24, 0x0d, 0x2f, 0x29, 0x2a, 0x53, 0x2b, 0x35, 0x31, 0x72, 0x44, 0x69, 0x73, 0x3a, 0x3b, 0x1f, 0x22, + 0x0d, 0x77, 0x15, 0x32, 0x25, 0x22, 0x33, 0x33, 0x22, 0x25, 0x32, 0x01, 0x0c, 0x32, 0x45, 0x24, 0x19, 0x24, 0x21, + 0x14, 0x1f, 0x22, 0x1a, 0x16, 0x6d, 0x1b, 0x22, 0x60, 0x51, 0x3d, 0x54, 0x2a, 0x16, 0x21, 0x1e, 0x15, 0x16, 0xa2, + 0x2e, 0x26, 0x26, 0x2e, 0x2c, 0x27, 0x27, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xb0, 0x03, 0x53, 0x02, 0xcf, 0x00, 0x3e, + 0x00, 0x4c, 0x00, 0x7e, 0x40, 0x16, 0x16, 0x01, 0x09, 0x02, 0x46, 0x01, 0x03, 0x09, 0x08, 0x01, 0x00, 0x03, 0x2e, + 0x01, 0x05, 0x00, 0x2f, 0x01, 0x06, 0x05, 0x05, 0x4c, 0x4b, 0xb0, 0x2c, 0x50, 0x58, 0x40, 0x26, 0x08, 0x01, 0x03, + 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, + 0x00, 0x07, 0x07, 0x6a, 0x4d, 0x00, 0x09, 0x09, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x24, + 0x00, 0x02, 0x00, 0x09, 0x03, 0x02, 0x09, 0x69, 0x08, 0x01, 0x03, 0x01, 0x01, 0x00, 0x05, 0x03, 0x00, 0x69, 0x00, + 0x05, 0x00, 0x06, 0x05, 0x06, 0x65, 0x00, 0x04, 0x04, 0x07, 0x61, 0x00, 0x07, 0x07, 0x6a, 0x04, 0x4e, 0x59, 0x40, + 0x0e, 0x4a, 0x48, 0x25, 0x27, 0x25, 0x25, 0x25, 0x28, 0x25, 0x25, 0x24, 0x0a, 0x0d, 0x1f, 0x2b, 0x01, 0x14, 0x0e, + 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x14, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x03, 0x53, 0x17, 0x2e, + 0x43, 0x2d, 0x27, 0x3c, 0x0e, 0x06, 0x15, 0x42, 0x2e, 0x56, 0x59, 0x37, 0x69, 0x4c, 0x2f, 0x5a, 0x1c, 0x0a, 0x01, + 0x17, 0x10, 0x17, 0x21, 0x11, 0x8e, 0x7d, 0x69, 0x8f, 0x4a, 0x8e, 0x8b, 0x39, 0x7e, 0x36, 0x31, 0x76, 0x42, 0x7c, + 0xb0, 0x5e, 0x3c, 0x70, 0x9f, 0x63, 0x6f, 0xa8, 0x5f, 0xfe, 0x12, 0x2a, 0x23, 0x2e, 0x28, 0x04, 0x05, 0x0b, 0x18, + 0x0e, 0x2c, 0x36, 0x19, 0x01, 0x6c, 0x2e, 0x5a, 0x49, 0x2b, 0x27, 0x1e, 0x1d, 0x28, 0x6a, 0x57, 0x42, 0x68, 0x3c, + 0x12, 0x0a, 0xcd, 0x0a, 0x17, 0x09, 0x23, 0x18, 0x2d, 0x4b, 0x2c, 0x7b, 0x8b, 0x56, 0x98, 0x62, 0x82, 0x94, 0x1a, + 0x13, 0x5e, 0x15, 0x17, 0x59, 0xa6, 0x74, 0x5b, 0x9c, 0x75, 0x40, 0x56, 0x9f, 0xa9, 0x37, 0x31, 0x48, 0x47, 0x5f, + 0x02, 0x04, 0x28, 0x3f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb4, 0x02, 0xcd, 0x00, 0x07, 0x00, 0x12, + 0x00, 0x2c, 0x40, 0x29, 0x0c, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x68, 0x00, + 0x02, 0x02, 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x12, 0x11, 0x00, 0x07, 0x00, + 0x07, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x21, 0x27, 0x23, 0x07, 0x23, 0x13, 0x33, 0x13, 0x01, 0x2e, 0x02, + 0x27, 0x0e, 0x02, 0x07, 0x07, 0x33, 0x02, 0x0f, 0x37, 0xfc, 0x37, 0xa5, 0xfb, 0xbc, 0xfd, 0xfe, 0xcf, 0x04, 0x11, + 0x10, 0x05, 0x04, 0x0f, 0x0e, 0x05, 0x33, 0xb5, 0xa8, 0xa8, 0x02, 0xcd, 0xfd, 0x33, 0x01, 0xc3, 0x0f, 0x3c, 0x3f, + 0x14, 0x17, 0x3b, 0x39, 0x13, 0x9b, 0x00, 0x00, 0x03, 0x00, 0x55, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x10, + 0x00, 0x19, 0x00, 0x22, 0x00, 0x44, 0x40, 0x41, 0x06, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x08, 0x01, + 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, + 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1a, 0x1a, 0x12, 0x11, 0x01, 0x00, 0x1a, 0x22, 0x1a, 0x21, 0x1d, + 0x1b, 0x18, 0x16, 0x11, 0x19, 0x12, 0x19, 0x0f, 0x0d, 0x00, 0x10, 0x01, 0x10, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x23, 0x21, 0x11, 0x13, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x1d, 0x02, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x01, 0x3c, 0x93, 0x86, 0x47, 0x32, 0x23, + 0x40, 0x28, 0x8d, 0x7a, 0xfe, 0xf5, 0xef, 0x41, 0x33, 0x3c, 0x3f, 0x4f, 0x61, 0x44, 0x35, 0x36, 0x48, 0x02, 0xca, + 0x57, 0x5b, 0x43, 0x4f, 0x0b, 0x05, 0x07, 0x24, 0x44, 0x38, 0x62, 0x6d, 0x02, 0xca, 0xfe, 0xe2, 0x30, 0x27, 0x29, + 0x27, 0xa7, 0x73, 0xc0, 0x37, 0x2b, 0x27, 0x37, 0x00, 0x01, 0x00, 0x37, 0xff, 0xf6, 0x02, 0x63, 0x02, 0xd4, 0x00, + 0x1a, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x00, 0x03, 0x18, 0x09, 0x02, 0x01, 0x00, 0x0a, 0x01, 0x02, 0x01, 0x03, + 0x4c, 0x04, 0x01, 0x00, 0x00, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x71, 0x02, 0x4e, 0x01, 0x00, 0x15, 0x13, 0x0d, 0x0b, 0x07, 0x05, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, + 0x2b, 0x01, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, + 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x01, 0x8e, 0x56, 0x63, 0x5f, 0x60, 0x2f, 0x57, 0x2c, 0x55, + 0x6e, 0x72, 0x93, 0x47, 0x50, 0x9a, 0x6f, 0x35, 0x6d, 0x31, 0x32, 0x24, 0x51, 0x02, 0x55, 0x81, 0x71, 0x71, 0x7d, + 0x16, 0x11, 0x82, 0x24, 0x5b, 0xa5, 0x6e, 0x6c, 0xa6, 0x5e, 0x17, 0x18, 0x7a, 0x11, 0x19, 0x00, 0x02, 0x00, 0x55, + 0x00, 0x00, 0x02, 0xa6, 0x02, 0xca, 0x00, 0x09, 0x00, 0x11, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x02, 0x02, 0x01, 0x5f, + 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x21, 0x24, 0x21, + 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, 0x23, 0x23, 0x11, 0x33, 0x32, 0x16, 0x07, 0x34, 0x26, 0x23, + 0x23, 0x11, 0x33, 0x32, 0x02, 0xa6, 0x5c, 0xa8, 0x73, 0xda, 0xec, 0xa8, 0xbd, 0xa0, 0x66, 0x63, 0x4f, 0x40, 0xd8, + 0x01, 0x71, 0x7b, 0xa4, 0x52, 0x02, 0xca, 0xb1, 0xae, 0x73, 0x6f, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, + 0x00, 0x01, 0xf5, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x29, 0x40, 0x26, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, + 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, 0x21, 0x11, 0x21, 0x15, 0x21, 0x15, + 0x33, 0x15, 0x23, 0x15, 0x21, 0x01, 0xf5, 0xfe, 0x65, 0x01, 0x9b, 0xfe, 0xfc, 0xf2, 0xf2, 0x01, 0x04, 0x02, 0xca, + 0x7c, 0x9d, 0x7c, 0xb8, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x01, 0xf3, 0x02, 0xca, 0x00, 0x09, 0x00, 0x23, + 0x40, 0x20, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x67, 0x00, 0x02, 0x02, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x10, 0x05, 0x0d, 0x1b, 0x2b, 0x33, 0x23, 0x11, + 0x21, 0x15, 0x21, 0x15, 0x33, 0x15, 0x23, 0xef, 0x95, 0x01, 0x99, 0xfe, 0xfc, 0xf2, 0xf2, 0x02, 0xca, 0x7c, 0xb8, + 0x7c, 0x00, 0x01, 0x00, 0x3a, 0xff, 0xf6, 0x02, 0x84, 0x02, 0xd4, 0x00, 0x20, 0x00, 0x3b, 0x40, 0x38, 0x0f, 0x01, + 0x03, 0x02, 0x10, 0x01, 0x00, 0x03, 0x1e, 0x01, 0x04, 0x05, 0x02, 0x01, 0x01, 0x04, 0x04, 0x4c, 0x00, 0x00, 0x00, + 0x05, 0x04, 0x00, 0x05, 0x67, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x01, + 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x13, 0x26, 0x25, 0x25, 0x23, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x21, + 0x11, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x35, 0x23, 0x01, 0x69, 0x01, 0x1b, 0x38, 0x79, 0x4d, + 0xa0, 0xac, 0x57, 0xa6, 0x78, 0x39, 0x6e, 0x2d, 0x32, 0x21, 0x54, 0x2e, 0x42, 0x61, 0x35, 0x26, 0x52, 0x42, 0x20, + 0x2d, 0x13, 0x87, 0x01, 0x91, 0xfe, 0x8e, 0x13, 0x16, 0xbc, 0xb4, 0x70, 0xa4, 0x5a, 0x18, 0x14, 0x79, 0x11, 0x16, + 0x3c, 0x6d, 0x4a, 0x46, 0x6c, 0x3d, 0x06, 0x04, 0x95, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa3, 0x02, 0xca, + 0x00, 0x0b, 0x00, 0x21, 0x40, 0x1e, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x01, 0x67, 0x05, 0x01, 0x03, 0x03, 0x6a, + 0x4d, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x21, + 0x23, 0x11, 0x21, 0x11, 0x23, 0x11, 0x33, 0x11, 0x21, 0x11, 0x33, 0x02, 0xa3, 0x97, 0xfe, 0xe5, 0x97, 0x97, 0x01, + 0x1b, 0x97, 0x01, 0x34, 0xfe, 0xcc, 0x02, 0xca, 0xfe, 0xe8, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, + 0x01, 0x65, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x0a, 0x09, 0x08, 0x05, 0x04, 0x03, 0x02, 0x08, + 0x00, 0x01, 0x01, 0x4c, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x10, 0x02, 0x0d, + 0x18, 0x2b, 0x21, 0x21, 0x35, 0x37, 0x11, 0x27, 0x35, 0x21, 0x15, 0x07, 0x11, 0x17, 0x01, 0x65, 0xfe, 0xbb, 0x57, + 0x57, 0x01, 0x45, 0x57, 0x57, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x00, 0x00, 0x01, + 0xff, 0xb6, 0xff, 0x2e, 0x00, 0xf1, 0x02, 0xca, 0x00, 0x11, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, 0x6a, 0x02, 0x4e, + 0x01, 0x00, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x11, 0x01, 0x11, 0x04, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x0f, 0x1d, 0x2c, 0x10, 0x10, 0x23, + 0x14, 0x1a, 0x2b, 0x18, 0x97, 0x39, 0x66, 0xd2, 0x07, 0x04, 0x7e, 0x04, 0x06, 0x14, 0x38, 0x34, 0x02, 0x9d, 0xfd, + 0x64, 0x5c, 0x71, 0x33, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x98, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x20, + 0x40, 0x1d, 0x0e, 0x08, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x15, 0x11, 0x13, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x07, 0x15, 0x23, + 0x11, 0x33, 0x11, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x02, 0x98, 0xac, 0xbb, 0x40, 0x97, 0x97, 0x0f, 0x1e, 0x0f, + 0xc1, 0xa8, 0xf9, 0x01, 0x2d, 0x2e, 0xff, 0x02, 0xca, 0xfe, 0xb9, 0x15, 0x2a, 0x15, 0xf3, 0xfe, 0xc4, 0x00, 0x01, + 0x00, 0x55, 0x00, 0x00, 0x02, 0x0f, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x00, 0x00, 0x6a, 0x4d, + 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x11, + 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x11, 0x33, 0x11, 0x21, 0x15, 0x55, 0x99, 0x01, 0x21, 0x02, 0xca, 0xfd, 0xb4, + 0x7e, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x55, 0x02, 0xca, 0x00, 0x17, 0x00, 0x26, 0x40, 0x23, 0x15, 0x0b, + 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x05, 0x04, 0x03, 0x03, 0x00, 0x00, 0x6b, 0x00, + 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x11, 0x13, 0x11, 0x17, 0x06, 0x0d, 0x1a, 0x2b, 0x21, 0x03, 0x23, 0x1e, + 0x02, 0x15, 0x11, 0x23, 0x11, 0x33, 0x13, 0x33, 0x13, 0x33, 0x11, 0x23, 0x11, 0x34, 0x36, 0x36, 0x37, 0x23, 0x03, + 0x01, 0x88, 0xac, 0x04, 0x01, 0x04, 0x04, 0x87, 0xce, 0xa9, 0x03, 0xb3, 0xce, 0x8d, 0x03, 0x03, 0x01, 0x04, 0xb8, + 0x02, 0x30, 0x14, 0x50, 0x5b, 0x25, 0xfe, 0xb4, 0x02, 0xca, 0xfd, 0xde, 0x02, 0x22, 0xfd, 0x36, 0x01, 0x52, 0x22, + 0x58, 0x4f, 0x14, 0xfd, 0xd1, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xd3, 0x02, 0xca, 0x00, 0x11, 0x00, 0x1e, + 0x40, 0x1b, 0x0b, 0x02, 0x02, 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, + 0x6b, 0x00, 0x4e, 0x16, 0x11, 0x16, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x01, 0x23, 0x16, 0x16, 0x17, 0x11, + 0x23, 0x11, 0x33, 0x01, 0x33, 0x26, 0x26, 0x27, 0x11, 0x33, 0x02, 0xd3, 0xc0, 0xfe, 0xc9, 0x04, 0x02, 0x05, 0x02, + 0x87, 0xbf, 0x01, 0x36, 0x03, 0x01, 0x04, 0x02, 0x88, 0x02, 0x1c, 0x33, 0x66, 0x33, 0xfe, 0xb0, 0x02, 0xca, 0xfd, + 0xe9, 0x32, 0x62, 0x31, 0x01, 0x52, 0x00, 0x02, 0x00, 0x37, 0xff, 0xf6, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x0f, 0x00, + 0x1b, 0x00, 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x26, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x06, + 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x49, 0x96, 0x75, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, 0x74, 0x97, 0x48, + 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x6f, 0xa5, 0x5c, 0x5c, 0xa6, 0x6f, 0x6e, + 0xa5, 0x5b, 0x5b, 0xa5, 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, + 0x43, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x32, 0x40, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x02, 0x04, 0x01, 0x69, + 0x06, 0x01, 0x03, 0x03, 0x00, 0x5f, 0x05, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0d, + 0x0c, 0x01, 0x00, 0x10, 0x0e, 0x0c, 0x14, 0x0d, 0x14, 0x0a, 0x09, 0x08, 0x06, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, + 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x23, 0x15, 0x23, 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, + 0x36, 0x35, 0x34, 0x26, 0x01, 0x35, 0x8a, 0x84, 0x34, 0x79, 0x67, 0x41, 0x99, 0xdb, 0x42, 0x33, 0x3f, 0x49, 0x3b, + 0x02, 0xca, 0x73, 0x69, 0x3f, 0x6e, 0x44, 0xfd, 0x02, 0xca, 0x7d, 0xd2, 0x32, 0x3c, 0x30, 0x34, 0x00, 0x02, 0x00, + 0x37, 0xff, 0x56, 0x02, 0xdf, 0x02, 0xd5, 0x00, 0x14, 0x00, 0x20, 0x00, 0x2b, 0x40, 0x28, 0x03, 0x01, 0x01, 0x03, + 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x86, 0x00, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x03, + 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x24, 0x25, 0x26, 0x41, 0x14, 0x05, 0x0d, 0x1b, 0x2b, 0x01, + 0x14, 0x06, 0x07, 0x17, 0x23, 0x27, 0x22, 0x22, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x02, 0xdf, 0x55, 0x5a, 0xad, 0xc5, + 0x7f, 0x03, 0x08, 0x03, 0x74, 0x97, 0x49, 0x49, 0x97, 0x75, 0x74, 0x97, 0x48, 0xfd, 0xf9, 0x55, 0x5e, 0x60, 0x53, + 0x53, 0x5f, 0x5f, 0x55, 0x01, 0x66, 0x77, 0xb0, 0x29, 0xc0, 0xa0, 0x5c, 0xa6, 0x6f, 0x6e, 0xa5, 0x5b, 0x5b, 0xa5, + 0x6f, 0x70, 0x7f, 0x7f, 0x70, 0x70, 0x80, 0x80, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x02, 0x91, 0x02, 0xca, 0x00, + 0x0c, 0x00, 0x15, 0x00, 0x3b, 0x40, 0x38, 0x05, 0x01, 0x02, 0x05, 0x01, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, + 0x02, 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x5f, 0x06, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x0e, 0x0d, 0x01, 0x00, 0x11, 0x0f, 0x0d, 0x15, 0x0e, 0x15, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x00, + 0x0c, 0x01, 0x0c, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x20, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, 0x11, 0x23, + 0x11, 0x17, 0x23, 0x15, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x01, 0x30, 0x01, 0x17, 0x4a, 0x37, 0xcb, 0xaf, 0x9f, + 0x55, 0x99, 0xd8, 0x3f, 0x3f, 0x3d, 0x42, 0x3d, 0x02, 0xca, 0xd0, 0x49, 0x5c, 0x1a, 0xfe, 0xc5, 0x01, 0x12, 0xfe, + 0xee, 0x02, 0xca, 0x77, 0xcb, 0x32, 0x39, 0x30, 0x30, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xff, 0x02, 0xd4, + 0x00, 0x28, 0x00, 0x2e, 0x40, 0x2b, 0x1b, 0x01, 0x03, 0x02, 0x1c, 0x06, 0x02, 0x01, 0x03, 0x05, 0x01, 0x00, 0x01, + 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x25, 0x2d, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x27, 0x35, + 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x2e, 0x03, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xff, 0x89, 0x7e, 0x71, 0x59, 0x33, + 0x6d, 0x36, 0x38, 0x2f, 0x25, 0x3e, 0x28, 0x19, 0x3a, 0x35, 0x22, 0x82, 0x70, 0x38, 0x65, 0x37, 0x31, 0x31, 0x4e, + 0x29, 0x2b, 0x2e, 0x44, 0x43, 0x37, 0x4d, 0x2a, 0xc6, 0x5f, 0x71, 0x2b, 0x8d, 0x16, 0x25, 0x2b, 0x21, 0x1b, 0x26, + 0x21, 0x13, 0x0c, 0x21, 0x31, 0x46, 0x31, 0x60, 0x6b, 0x1a, 0x18, 0x76, 0x14, 0x16, 0x28, 0x20, 0x26, 0x2c, 0x20, + 0x1a, 0x38, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x00, 0x02, 0x2e, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1b, 0x40, + 0x18, 0x03, 0x01, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, + 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x11, 0x23, 0x35, 0x21, 0x15, 0x23, 0x01, 0x6d, 0x99, 0xc1, + 0x02, 0x1b, 0xc1, 0x02, 0x4b, 0x7f, 0x7f, 0x00, 0x01, 0x00, 0x55, 0xff, 0xf6, 0x02, 0x9f, 0x02, 0xca, 0x00, 0x12, + 0x00, 0x1b, 0x40, 0x18, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x00, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x13, 0x23, 0x13, 0x23, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, + 0x33, 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x33, 0x02, 0x9f, 0x41, 0x83, 0x64, 0x8e, 0x94, 0x97, 0x48, + 0x47, 0x4a, 0x43, 0x97, 0xfc, 0x4a, 0x77, 0x45, 0x91, 0x77, 0x01, 0xcc, 0xfe, 0x4b, 0x58, 0x48, 0x4e, 0x53, 0x01, + 0xb4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x21, 0x40, 0x1e, 0x09, + 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x01, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, + 0x17, 0x3e, 0x02, 0x37, 0x13, 0x02, 0x8a, 0xf3, 0xa5, 0xf2, 0x99, 0x86, 0x04, 0x0f, 0x10, 0x03, 0x03, 0x0f, 0x10, + 0x03, 0x87, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0xfe, 0x57, 0x0b, 0x3b, 0x41, 0x16, 0x16, 0x41, 0x3b, 0x0b, 0x01, + 0xa9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc7, 0x02, 0xca, 0x00, 0x26, 0x00, 0x27, 0x40, 0x24, 0x21, 0x16, + 0x08, 0x03, 0x00, 0x02, 0x01, 0x4c, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0x1a, 0x11, 0x1c, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x01, 0x03, 0x23, + 0x03, 0x2e, 0x03, 0x27, 0x0e, 0x03, 0x07, 0x03, 0x23, 0x03, 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, + 0x33, 0x13, 0x1e, 0x02, 0x17, 0x3e, 0x02, 0x37, 0x13, 0x03, 0xc7, 0xb6, 0xac, 0x61, 0x03, 0x09, 0x0b, 0x08, 0x02, + 0x01, 0x09, 0x0a, 0x0a, 0x03, 0x60, 0xac, 0xb6, 0x95, 0x5b, 0x06, 0x0e, 0x0c, 0x03, 0x03, 0x0c, 0x0d, 0x05, 0x68, + 0x8f, 0x68, 0x05, 0x0d, 0x0c, 0x03, 0x03, 0x0c, 0x0f, 0x05, 0x5b, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x77, 0x0b, 0x2c, + 0x34, 0x2f, 0x0d, 0x0d, 0x2f, 0x33, 0x2d, 0x0c, 0xfe, 0x8a, 0x02, 0xca, 0xfe, 0x7a, 0x17, 0x46, 0x46, 0x18, 0x19, + 0x45, 0x41, 0x12, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x42, 0x46, 0x18, 0x19, 0x45, 0x46, 0x17, 0x01, 0x86, 0x00, 0x01, + 0x00, 0x03, 0x00, 0x00, 0x02, 0x9a, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x20, 0x40, 0x1d, 0x0b, 0x08, 0x05, 0x02, 0x04, + 0x00, 0x02, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6a, 0x4d, 0x01, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x12, + 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x23, 0x03, 0x03, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x02, + 0x9a, 0xb0, 0x9e, 0x9f, 0xaa, 0xed, 0xdf, 0xaa, 0x93, 0x90, 0xab, 0xe0, 0x01, 0x01, 0xfe, 0xff, 0x01, 0x70, 0x01, + 0x5a, 0xf4, 0xf4, 0xfe, 0x9d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x72, 0x02, 0xca, 0x00, 0x08, 0x00, + 0x1c, 0x40, 0x19, 0x06, 0x03, 0x02, 0x01, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, + 0x6b, 0x01, 0x4e, 0x12, 0x12, 0x11, 0x03, 0x0d, 0x19, 0x2b, 0x01, 0x13, 0x33, 0x03, 0x11, 0x23, 0x11, 0x03, 0x33, + 0x01, 0x39, 0x93, 0xa6, 0xec, 0x9a, 0xec, 0xa6, 0x01, 0x9f, 0x01, 0x2b, 0xfe, 0x4c, 0xfe, 0xea, 0x01, 0x11, 0x01, + 0xb9, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x02, 0x2b, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x4d, + 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, + 0x21, 0x21, 0x35, 0x01, 0x21, 0x35, 0x21, 0x15, 0x01, 0x21, 0x02, 0x2b, 0xfd, 0xed, 0x01, 0x56, 0xfe, 0xb3, 0x02, + 0x01, 0xfe, 0xaa, 0x01, 0x5f, 0x62, 0x01, 0xeb, 0x7d, 0x62, 0xfe, 0x15, 0x00, 0x01, 0x00, 0x46, 0xff, 0x62, 0x01, + 0x32, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x63, 0x00, 0x02, 0x02, + 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x02, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x05, 0x23, 0x11, + 0x33, 0x15, 0x23, 0x11, 0x33, 0x01, 0x32, 0xec, 0xec, 0x6d, 0x6d, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x00, 0x01, + 0x00, 0x06, 0xff, 0xfa, 0x01, 0x99, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, + 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x13, + 0x01, 0x23, 0x01, 0x8e, 0x01, 0x0b, 0x89, 0xfe, 0xf6, 0x02, 0xd0, 0xfd, 0x2a, 0x02, 0xd6, 0x00, 0x00, 0x01, 0x00, + 0x19, 0xff, 0x62, 0x01, 0x05, 0x02, 0xca, 0x00, 0x07, 0x00, 0x1c, 0x40, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x63, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x11, 0x11, 0x11, 0x10, 0x04, 0x0d, 0x1a, + 0x2b, 0x17, 0x33, 0x11, 0x23, 0x35, 0x33, 0x11, 0x23, 0x19, 0x6d, 0x6d, 0xec, 0xec, 0x37, 0x02, 0x9a, 0x67, 0xfc, + 0x98, 0x00, 0x00, 0x01, 0x00, 0x17, 0x00, 0xfe, 0x02, 0x25, 0x02, 0xce, 0x00, 0x06, 0x00, 0x27, 0xb1, 0x06, 0x64, + 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, 0x03, 0x02, 0x02, 0x01, 0x01, + 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x37, 0x13, + 0x33, 0x13, 0x23, 0x03, 0x03, 0x17, 0xd6, 0x46, 0xf2, 0x75, 0x9d, 0x89, 0xfe, 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x3a, + 0xfe, 0xc6, 0x00, 0x01, 0xff, 0xfe, 0xff, 0x62, 0x01, 0x9d, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x20, 0xb1, 0x06, 0x64, + 0x44, 0x40, 0x15, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, + 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x05, 0x21, 0x35, 0x21, 0x01, 0x9d, 0xfe, 0x61, 0x01, + 0x9f, 0x9e, 0x44, 0x00, 0x01, 0x00, 0x28, 0x02, 0x5e, 0x01, 0x45, 0x02, 0xfe, 0x00, 0x0c, 0x00, 0x26, 0xb1, 0x06, + 0x64, 0x44, 0x40, 0x1b, 0x0b, 0x04, 0x02, 0x00, 0x01, 0x01, 0x4c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x85, 0x00, 0x00, + 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x13, 0x1e, + 0x02, 0x17, 0x15, 0x23, 0x2e, 0x03, 0x27, 0x35, 0xd1, 0x0f, 0x2a, 0x2a, 0x11, 0x65, 0x13, 0x33, 0x35, 0x2f, 0x0e, + 0x02, 0xfe, 0x16, 0x37, 0x33, 0x13, 0x0d, 0x0d, 0x27, 0x2c, 0x28, 0x0e, 0x0a, 0x00, 0x02, 0x00, 0x28, 0xff, 0xf6, + 0x02, 0x10, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x26, 0x00, 0x7b, 0x40, 0x0e, 0x19, 0x01, 0x04, 0x00, 0x18, 0x01, 0x03, + 0x04, 0x06, 0x01, 0x01, 0x06, 0x03, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x20, 0x00, 0x03, 0x08, 0x01, 0x05, + 0x06, 0x03, 0x05, 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x01, + 0x61, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, 0x24, 0x00, 0x03, 0x08, 0x01, 0x05, 0x06, 0x03, 0x05, + 0x69, 0x00, 0x04, 0x04, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x00, 0x06, + 0x06, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x1d, 0x1c, 0x01, 0x00, 0x23, 0x21, 0x1c, + 0x26, 0x1d, 0x26, 0x16, 0x14, 0x11, 0x0f, 0x0b, 0x09, 0x05, 0x04, 0x00, 0x1b, 0x01, 0x1b, 0x09, 0x0d, 0x16, 0x2b, + 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x37, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x13, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x01, 0x3d, 0x66, 0x6d, 0x69, 0x1d, 0x04, 0x24, 0x4d, 0x45, 0x48, 0x60, 0x7c, 0x7b, 0x5b, 0x2d, 0x27, 0x25, + 0x4e, 0x26, 0x2c, 0x2b, 0x6f, 0x46, 0x48, 0x37, 0x27, 0x21, 0x2f, 0x41, 0x02, 0x2c, 0x61, 0x5f, 0xfe, 0x94, 0x4a, + 0x2c, 0x28, 0x54, 0x57, 0x55, 0x57, 0x05, 0x03, 0x11, 0x31, 0x27, 0x18, 0x11, 0x67, 0x16, 0x1a, 0xfe, 0xce, 0x02, + 0x2a, 0x26, 0x23, 0x21, 0x38, 0x34, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x49, 0xff, 0xf6, 0x02, 0x48, 0x02, 0xf8, 0x00, + 0x15, 0x00, 0x21, 0x00, 0x6b, 0xb5, 0x03, 0x01, 0x05, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x21, + 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, + 0x6c, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x03, 0x01, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x1b, 0x40, 0x25, 0x07, 0x01, + 0x05, 0x05, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x04, 0x5f, 0x00, 0x04, 0x04, 0x6c, 0x4d, + 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x59, 0x40, 0x10, + 0x17, 0x16, 0x1e, 0x1c, 0x16, 0x21, 0x17, 0x21, 0x11, 0x11, 0x12, 0x24, 0x26, 0x08, 0x0d, 0x1b, 0x2b, 0x13, 0x14, + 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x07, 0x23, 0x11, + 0x33, 0x13, 0x22, 0x06, 0x15, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0xe0, 0x04, 0x02, 0x06, 0x16, 0x4a, + 0x3b, 0x5b, 0x72, 0x73, 0x5e, 0x3c, 0x45, 0x16, 0x0a, 0x19, 0x74, 0x97, 0x6a, 0x39, 0x31, 0x2f, 0x3d, 0x31, 0x32, + 0x02, 0x47, 0x1f, 0x38, 0x15, 0x22, 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x3b, 0x02, 0xf8, 0xfe, 0xbc, 0x48, + 0x4d, 0x12, 0x4e, 0x4f, 0x54, 0x50, 0xa0, 0x00, 0x01, 0x00, 0x2f, 0xff, 0xf6, 0x01, 0xe8, 0x02, 0x2c, 0x00, 0x1b, + 0x00, 0x37, 0x40, 0x34, 0x0b, 0x01, 0x02, 0x01, 0x18, 0x0c, 0x02, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x03, 0x4c, + 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x16, 0x14, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x05, 0x0d, 0x16, 0x2b, + 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, + 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x01, 0x37, 0x4f, 0x77, 0x42, 0x48, 0x7c, 0x4f, 0x2f, 0x56, + 0x21, 0x2d, 0x1e, 0x3d, 0x1e, 0x3a, 0x3f, 0x3f, 0x38, 0x2a, 0x4e, 0x21, 0x20, 0x4d, 0x0a, 0x3b, 0x7c, 0x61, 0x64, + 0x7f, 0x3b, 0x14, 0x11, 0x72, 0x0d, 0x11, 0x52, 0x52, 0x51, 0x4e, 0x17, 0x13, 0x7b, 0x13, 0x16, 0x00, 0x02, 0x00, + 0x2f, 0xff, 0xf6, 0x02, 0x2f, 0x02, 0xf8, 0x00, 0x15, 0x00, 0x22, 0x00, 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x09, 0x01, 0x05, 0x01, 0x12, + 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, + 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, + 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, 0x22, 0x17, 0x22, 0x11, 0x10, 0x0f, 0x0e, + 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x33, 0x26, 0x26, 0x35, 0x35, 0x33, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x27, 0x32, 0x36, 0x37, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0xfc, 0x5b, 0x72, 0x74, 0x5e, 0x3a, 0x48, 0x17, 0x05, 0x03, 0x05, 0x98, + 0x74, 0x1e, 0x06, 0x15, 0x4a, 0x07, 0x3d, 0x32, 0x01, 0x30, 0x41, 0x31, 0x37, 0x37, 0x0a, 0x8f, 0x8b, 0x8d, 0x8f, + 0x2e, 0x22, 0x12, 0x41, 0x1b, 0xae, 0xfd, 0x08, 0x47, 0x22, 0x2f, 0x79, 0x47, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, + 0x50, 0x4f, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x1c, 0x00, 0x43, + 0x40, 0x40, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x01, 0x02, 0x05, 0x01, + 0x67, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, + 0x03, 0x03, 0x71, 0x03, 0x4e, 0x17, 0x16, 0x01, 0x00, 0x1a, 0x19, 0x16, 0x1c, 0x17, 0x1c, 0x10, 0x0e, 0x09, 0x07, + 0x05, 0x04, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x15, 0x21, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x07, 0x33, 0x26, + 0x26, 0x01, 0x32, 0x72, 0x83, 0xfe, 0xa1, 0x03, 0x47, 0x43, 0x33, 0x54, 0x2c, 0x28, 0x5a, 0x41, 0x51, 0x7d, 0x48, + 0x8f, 0x78, 0x2d, 0x39, 0x04, 0xce, 0x01, 0x31, 0x02, 0x2c, 0x80, 0x78, 0x49, 0x3e, 0x47, 0x14, 0x14, 0x71, 0x14, + 0x13, 0x3d, 0x7c, 0x5e, 0x8f, 0x90, 0x6b, 0x39, 0x38, 0x31, 0x40, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x01, 0xb0, + 0x02, 0xfd, 0x00, 0x18, 0x00, 0x86, 0x40, 0x13, 0x0f, 0x01, 0x04, 0x03, 0x10, 0x01, 0x05, 0x04, 0x06, 0x01, 0x00, + 0x05, 0x03, 0x4c, 0x07, 0x01, 0x05, 0x01, 0x4b, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, + 0x03, 0x6c, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x1b, 0x40, 0x1b, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x02, 0x01, 0x00, 0x00, 0x05, + 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x59, 0x40, 0x09, 0x13, 0x25, 0x26, + 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, 0x23, 0x11, 0x23, 0x11, 0x23, 0x35, 0x37, 0x35, 0x34, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x15, 0x33, 0x01, 0x7c, 0x81, 0x95, 0x52, 0x52, + 0x2f, 0x57, 0x3b, 0x2c, 0x47, 0x16, 0x26, 0x11, 0x28, 0x1a, 0x1f, 0x1d, 0x81, 0x01, 0xb2, 0xfe, 0x4e, 0x01, 0xb2, + 0x48, 0x28, 0x28, 0x46, 0x4d, 0x20, 0x0e, 0x09, 0x6d, 0x05, 0x09, 0x26, 0x1d, 0x22, 0x00, 0x02, 0x00, 0x2f, 0xff, + 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, 0x21, 0x00, 0x2d, 0x00, 0x9e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x03, + 0x01, 0x05, 0x00, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, 0x1b, 0x40, + 0x12, 0x03, 0x01, 0x05, 0x01, 0x18, 0x01, 0x04, 0x06, 0x0e, 0x01, 0x03, 0x04, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x4c, + 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x01, 0x07, 0x02, 0x00, 0x00, + 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, + 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x00, 0x61, 0x07, + 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x06, 0x06, 0x04, 0x61, 0x00, 0x04, 0x04, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x02, + 0x61, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x19, 0x23, 0x22, 0x01, 0x00, 0x28, 0x26, 0x22, 0x2d, 0x23, + 0x2d, 0x1d, 0x1b, 0x12, 0x10, 0x0b, 0x09, 0x06, 0x05, 0x00, 0x21, 0x01, 0x21, 0x09, 0x0d, 0x16, 0x2b, 0x13, 0x32, + 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, + 0x35, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x06, 0x15, 0x14, 0x33, + 0x32, 0x36, 0x35, 0x35, 0x34, 0x26, 0xff, 0x38, 0x4d, 0x19, 0x05, 0x0d, 0x80, 0x86, 0x8c, 0x3f, 0x64, 0x2c, 0x2e, + 0x5e, 0x3e, 0x3e, 0x42, 0x03, 0x02, 0x05, 0x17, 0x4b, 0x38, 0x5f, 0x70, 0x72, 0x8f, 0x32, 0x35, 0x6a, 0x3c, 0x33, + 0x33, 0x02, 0x2c, 0x2b, 0x24, 0x45, 0xfd, 0xda, 0x74, 0x78, 0x0f, 0x12, 0x80, 0x14, 0x16, 0x3a, 0x33, 0x0f, 0x0c, + 0x28, 0x0f, 0x24, 0x2c, 0x92, 0x88, 0x88, 0x94, 0x77, 0x56, 0x51, 0xa2, 0x46, 0x4a, 0x16, 0x52, 0x51, 0x00, 0x01, + 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0xf8, 0x00, 0x16, 0x00, 0x27, 0x40, 0x24, 0x03, 0x01, 0x02, 0x00, 0x01, + 0x4c, 0x00, 0x04, 0x04, 0x6c, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x11, 0x13, 0x22, 0x13, 0x26, 0x05, 0x0d, 0x1b, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0xe0, 0x04, + 0x03, 0x08, 0x1b, 0x51, 0x32, 0x58, 0x6c, 0x97, 0x57, 0x43, 0x32, 0x97, 0x97, 0x02, 0x5f, 0x2d, 0x43, 0x13, 0x2a, + 0x26, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, 0xf8, 0x00, 0x00, 0x02, 0x00, 0x44, + 0x00, 0x00, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x72, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0c, + 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, + 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x11, 0x23, 0x11, 0x96, 0x21, 0x31, + 0x31, 0x21, 0x22, 0x30, 0x30, 0x6d, 0x97, 0x02, 0xf9, 0x1f, 0x2b, 0x29, 0x20, 0x20, 0x29, 0x2b, 0x1f, 0xd7, 0xfd, + 0xde, 0x02, 0x22, 0x00, 0x02, 0xff, 0xcb, 0xff, 0x10, 0x00, 0xe8, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1c, 0x00, 0x37, + 0x40, 0x34, 0x10, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, + 0x00, 0x72, 0x4d, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, 0x05, 0x01, 0x02, 0x02, 0x6f, 0x02, + 0x4e, 0x0d, 0x0c, 0x18, 0x17, 0x14, 0x12, 0x0c, 0x1c, 0x0d, 0x1c, 0x24, 0x22, 0x06, 0x0d, 0x18, 0x2b, 0x13, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x03, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x35, 0x11, 0x33, 0x11, 0x14, 0x06, 0x06, 0x44, 0x2f, 0x23, 0x21, 0x31, 0x31, 0x21, 0x23, 0x2f, 0x1c, 0x18, + 0x33, 0x12, 0x10, 0x1c, 0x12, 0x1b, 0x25, 0x97, 0x24, 0x51, 0x02, 0xaf, 0x2b, 0x1f, 0x1f, 0x2b, 0x29, 0x20, 0x20, + 0xfc, 0x8a, 0x07, 0x05, 0x77, 0x05, 0x05, 0x22, 0x32, 0x02, 0x45, 0xfd, 0xa3, 0x32, 0x52, 0x31, 0x00, 0x01, 0x00, + 0x4e, 0x00, 0x00, 0x02, 0x6c, 0x02, 0xf8, 0x00, 0x12, 0x00, 0x24, 0x40, 0x21, 0x0e, 0x0d, 0x0a, 0x03, 0x04, 0x01, + 0x00, 0x01, 0x4c, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, + 0x4e, 0x11, 0x13, 0x12, 0x18, 0x04, 0x0d, 0x1a, 0x2b, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x37, 0x33, + 0x07, 0x13, 0x23, 0x27, 0x07, 0x15, 0x23, 0x11, 0x33, 0xe3, 0x05, 0x03, 0x02, 0x0f, 0x20, 0x12, 0x99, 0xa8, 0xd9, + 0xe6, 0xac, 0x9d, 0x40, 0x95, 0x95, 0x01, 0xa4, 0x1f, 0x3d, 0x1f, 0x15, 0x2b, 0x13, 0xa6, 0xed, 0xfe, 0xcb, 0xdd, + 0x33, 0xaa, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x00, 0xe0, 0x02, 0xf8, 0x00, 0x03, 0x00, 0x13, 0x40, + 0x10, 0x00, 0x01, 0x01, 0x6c, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x11, 0x10, 0x02, 0x0d, 0x18, 0x2b, 0x33, + 0x23, 0x11, 0x33, 0xe0, 0x97, 0x97, 0x02, 0xf8, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x03, 0x88, 0x02, 0x2c, 0x00, + 0x24, 0x00, 0x6c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb6, 0x21, 0x1a, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb6, 0x21, + 0x1a, 0x02, 0x02, 0x06, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x04, 0x01, 0x02, 0x02, 0x00, + 0x61, 0x07, 0x06, 0x08, 0x03, 0x00, 0x00, 0x73, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x1b, 0x40, + 0x1a, 0x00, 0x06, 0x06, 0x6d, 0x4d, 0x04, 0x01, 0x02, 0x02, 0x00, 0x61, 0x07, 0x08, 0x02, 0x00, 0x00, 0x73, 0x4d, + 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x17, 0x01, 0x00, 0x1f, 0x1d, 0x19, 0x18, 0x17, 0x16, + 0x13, 0x11, 0x0e, 0x0d, 0x0a, 0x08, 0x05, 0x04, 0x00, 0x24, 0x01, 0x24, 0x09, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, + 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, + 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, 0x36, 0x02, 0xca, 0x5e, 0x60, + 0x96, 0x2a, 0x2a, 0x3b, 0x2f, 0x97, 0x28, 0x2a, 0x3e, 0x2d, 0x97, 0x74, 0x16, 0x05, 0x17, 0x54, 0x38, 0x3d, 0x51, + 0x17, 0x05, 0x1b, 0x56, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x3f, 0x37, 0x55, 0x4e, 0xfe, 0xef, 0x01, + 0x3e, 0x3d, 0x39, 0x5d, 0x57, 0xff, 0x00, 0x02, 0x22, 0x46, 0x25, 0x2b, 0x2a, 0x28, 0x29, 0x29, 0x00, 0x00, 0x01, + 0x00, 0x49, 0x00, 0x00, 0x02, 0x43, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x10, + 0x01, 0x02, 0x00, 0x01, 0x4c, 0x1b, 0xb5, 0x10, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x13, 0x00, 0x02, 0x02, 0x00, 0x61, 0x04, 0x05, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1b, 0x40, 0x17, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x05, 0x01, 0x00, 0x00, + 0x73, 0x4d, 0x03, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x09, + 0x07, 0x05, 0x04, 0x00, 0x12, 0x01, 0x12, 0x06, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x11, 0x23, 0x11, 0x34, + 0x23, 0x22, 0x06, 0x15, 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x01, 0x81, 0x5a, 0x68, 0x96, 0x58, 0x44, 0x31, + 0x97, 0x74, 0x15, 0x06, 0x36, 0x02, 0x2c, 0x5f, 0x69, 0xfe, 0x9c, 0x01, 0x3e, 0x76, 0x5d, 0x57, 0xff, 0x00, 0x02, + 0x22, 0x49, 0x53, 0x00, 0x00, 0x02, 0x00, 0x2f, 0xff, 0xf6, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x0d, 0x00, 0x19, 0x00, + 0x1f, 0x40, 0x1c, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, 0x00, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x24, 0x25, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x01, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x16, 0x05, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x02, 0x41, 0x8f, 0x7b, 0x4d, 0x77, 0x44, 0x8f, 0x7c, 0x4d, 0x76, 0x44, 0xfe, 0x88, 0x34, 0x3c, 0x3a, 0x34, + 0x34, 0x3b, 0x3b, 0x34, 0x01, 0x12, 0x88, 0x94, 0x42, 0x7f, 0x5b, 0x88, 0x92, 0x41, 0x7e, 0x5b, 0x50, 0x59, 0x59, + 0x50, 0x51, 0x56, 0x56, 0x00, 0x02, 0x00, 0x49, 0xff, 0x10, 0x02, 0x48, 0x02, 0x2c, 0x00, 0x15, 0x00, 0x21, 0x00, + 0x82, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x12, 0x01, 0x04, 0x00, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x1b, + 0x40, 0x0a, 0x12, 0x01, 0x04, 0x03, 0x09, 0x01, 0x01, 0x05, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, + 0x1d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x03, 0x03, 0x6d, 0x4d, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, + 0x01, 0x71, 0x4d, 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x10, 0x0f, 0x0e, 0x07, 0x05, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x01, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x23, 0x16, 0x16, 0x15, 0x15, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, + 0x36, 0x17, 0x22, 0x06, 0x07, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x01, 0x7b, 0x5e, 0x6f, 0x75, 0x5c, + 0x3c, 0x47, 0x14, 0x06, 0x02, 0x04, 0x97, 0x7b, 0x15, 0x07, 0x16, 0x48, 0x0b, 0x3a, 0x2d, 0x02, 0x2d, 0x3d, 0x33, + 0x32, 0x02, 0x2c, 0x8f, 0x8b, 0x8c, 0x90, 0x2b, 0x1a, 0x12, 0x2f, 0x19, 0xd1, 0x03, 0x12, 0x47, 0x21, 0x30, 0x78, + 0x48, 0x49, 0x10, 0x4f, 0x54, 0x54, 0x50, 0xa0, 0x00, 0x02, 0x00, 0x2f, 0xff, 0x10, 0x02, 0x2f, 0x02, 0x2c, 0x00, + 0x15, 0x00, 0x21, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x01, 0x03, 0x01, 0x00, + 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x10, 0x01, 0x05, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, + 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, 0x40, 0x0f, 0x17, 0x16, 0x1e, 0x1c, 0x16, + 0x21, 0x17, 0x21, 0x11, 0x14, 0x24, 0x26, 0x07, 0x0d, 0x1a, 0x2b, 0x05, 0x34, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x11, 0x23, 0x03, 0x32, 0x36, 0x35, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x01, 0x98, 0x02, 0x03, 0x06, 0x15, 0x49, 0x3c, 0x5c, 0x72, 0x74, 0x5d, + 0x3c, 0x4a, 0x17, 0x04, 0x0e, 0x80, 0x97, 0x65, 0x3d, 0x31, 0x2f, 0x42, 0x34, 0x33, 0x0b, 0x13, 0x2c, 0x13, 0x22, + 0x2f, 0x8f, 0x8b, 0x8c, 0x90, 0x2e, 0x22, 0x46, 0xfc, 0xee, 0x01, 0x5d, 0x47, 0x49, 0x15, 0x4f, 0x55, 0x58, 0x50, + 0xa1, 0x00, 0x00, 0x01, 0x00, 0x49, 0x00, 0x00, 0x01, 0xb3, 0x02, 0x2c, 0x00, 0x13, 0x00, 0x69, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x0b, 0x10, 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x02, 0x4c, 0x1b, 0x40, 0x0e, 0x03, + 0x01, 0x03, 0x00, 0x10, 0x01, 0x01, 0x03, 0x04, 0x01, 0x02, 0x01, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x12, 0x00, 0x01, 0x01, 0x00, 0x61, 0x03, 0x04, 0x02, 0x00, 0x00, 0x73, 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, + 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x73, + 0x4d, 0x00, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0f, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x08, 0x06, 0x00, + 0x13, 0x01, 0x13, 0x05, 0x0d, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x11, 0x23, 0x11, 0x33, 0x17, 0x33, 0x36, 0x36, 0x01, 0x77, 0x0f, 0x22, 0x0b, 0x0f, 0x0b, 0x1e, 0x15, 0x1f, 0x3e, + 0x29, 0x97, 0x73, 0x16, 0x07, 0x18, 0x53, 0x02, 0x2c, 0x04, 0x02, 0x8d, 0x03, 0x03, 0x1a, 0x3c, 0x34, 0xfe, 0xeb, + 0x02, 0x22, 0x5c, 0x2a, 0x3c, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xcc, 0x02, 0x2c, 0x00, 0x27, 0x00, 0x2e, + 0x40, 0x2b, 0x1a, 0x01, 0x03, 0x02, 0x1b, 0x07, 0x02, 0x01, 0x03, 0x06, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x25, 0x2b, 0x25, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0x25, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x15, 0x14, 0x16, 0x16, 0x17, 0x1e, 0x02, 0x01, 0xcc, 0x6f, 0x73, 0x3a, 0x58, 0x29, 0x2c, 0x65, 0x26, + 0x2e, 0x29, 0x15, 0x35, 0x31, 0x49, 0x4b, 0x77, 0x62, 0x34, 0x5c, 0x2f, 0x2c, 0x26, 0x50, 0x1f, 0x48, 0x15, 0x35, + 0x30, 0x31, 0x43, 0x21, 0xa1, 0x4e, 0x5d, 0x0f, 0x11, 0x7d, 0x15, 0x18, 0x1a, 0x16, 0x0f, 0x18, 0x1a, 0x13, 0x1d, + 0x47, 0x44, 0x4c, 0x4e, 0x16, 0x14, 0x67, 0x11, 0x16, 0x28, 0x0f, 0x15, 0x18, 0x13, 0x14, 0x2a, 0x3d, 0x00, 0x01, + 0x00, 0x17, 0xff, 0xf6, 0x01, 0x92, 0x02, 0x96, 0x00, 0x18, 0x00, 0x40, 0x40, 0x3d, 0x0e, 0x01, 0x02, 0x04, 0x03, + 0x01, 0x00, 0x02, 0x04, 0x01, 0x01, 0x00, 0x03, 0x4c, 0x00, 0x03, 0x04, 0x03, 0x85, 0x05, 0x01, 0x02, 0x02, 0x04, + 0x5f, 0x00, 0x04, 0x04, 0x6d, 0x4d, 0x06, 0x01, 0x00, 0x00, 0x01, 0x62, 0x00, 0x01, 0x01, 0x71, 0x01, 0x4e, 0x01, + 0x00, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x18, 0x01, 0x18, 0x07, 0x0d, 0x16, 0x2b, + 0x25, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x11, 0x23, 0x35, 0x37, 0x37, 0x33, 0x15, + 0x33, 0x15, 0x23, 0x11, 0x14, 0x16, 0x01, 0x34, 0x19, 0x2e, 0x17, 0x18, 0x47, 0x2a, 0x31, 0x4d, 0x2d, 0x47, 0x52, + 0x2b, 0x5f, 0x99, 0x99, 0x24, 0x6d, 0x0a, 0x07, 0x6f, 0x0a, 0x0f, 0x20, 0x4f, 0x46, 0x01, 0x07, 0x3f, 0x32, 0x73, + 0x74, 0x70, 0xfe, 0xf9, 0x1f, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x46, 0xff, 0xf6, 0x02, 0x40, 0x02, 0x22, 0x00, 0x14, + 0x00, 0x50, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x18, 0x00, 0x01, 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, + 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x00, 0x62, 0x02, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, 0x01, + 0x01, 0x03, 0x5f, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x00, 0x04, 0x04, 0x02, + 0x62, 0x00, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x59, 0x40, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x23, 0x13, 0x22, + 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x01, 0x11, 0x23, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x11, 0x33, + 0x11, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x11, 0x02, 0x40, 0x74, 0x13, 0x09, 0x1a, 0x5a, 0x34, 0x57, 0x6b, 0x98, + 0x29, 0x2d, 0x44, 0x31, 0x02, 0x22, 0xfd, 0xde, 0x46, 0x2a, 0x26, 0x5f, 0x69, 0x01, 0x64, 0xfe, 0xc2, 0x3a, 0x3b, + 0x5c, 0x57, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, + 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, + 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, + 0x16, 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0xd0, 0xd0, 0x9e, 0x66, 0x05, 0x0f, 0x02, 0x04, 0x02, 0x0f, + 0x06, 0x68, 0x9e, 0xd0, 0x02, 0x22, 0xfe, 0xbe, 0x10, 0x37, 0x13, 0x14, 0x33, 0x12, 0x01, 0x43, 0xfd, 0xde, 0x00, + 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x4e, 0x02, 0x22, 0x00, 0x2a, 0x00, 0x21, 0x40, 0x1e, 0x21, 0x14, 0x05, + 0x03, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x02, 0x02, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x4e, + 0x11, 0x1b, 0x1c, 0x11, 0x1c, 0x05, 0x0d, 0x1b, 0x2b, 0x25, 0x2e, 0x03, 0x27, 0x23, 0x0e, 0x03, 0x07, 0x07, 0x23, + 0x03, 0x33, 0x17, 0x1e, 0x02, 0x17, 0x33, 0x3e, 0x03, 0x37, 0x13, 0x33, 0x13, 0x1e, 0x02, 0x15, 0x33, 0x3e, 0x02, + 0x37, 0x37, 0x33, 0x03, 0x23, 0x01, 0xe5, 0x04, 0x0f, 0x12, 0x10, 0x03, 0x04, 0x03, 0x0f, 0x12, 0x10, 0x04, 0x2c, + 0xa0, 0x9b, 0x94, 0x3f, 0x07, 0x0b, 0x0a, 0x02, 0x04, 0x01, 0x06, 0x09, 0x07, 0x02, 0x43, 0xa4, 0x40, 0x04, 0x0b, + 0x09, 0x04, 0x02, 0x0a, 0x0d, 0x07, 0x41, 0x92, 0x9d, 0xa2, 0xbf, 0x11, 0x43, 0x4d, 0x41, 0x0f, 0x0f, 0x41, 0x4d, + 0x44, 0x12, 0xbd, 0x02, 0x22, 0xf2, 0x19, 0x46, 0x41, 0x13, 0x0e, 0x2f, 0x32, 0x29, 0x07, 0x01, 0x06, 0xfe, 0xfa, + 0x0e, 0x3e, 0x40, 0x13, 0x11, 0x41, 0x48, 0x19, 0xf2, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x02, + 0x3d, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x1f, 0x40, 0x1c, 0x09, 0x06, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x12, 0x12, 0x12, 0x11, 0x04, 0x0d, 0x1a, 0x2b, + 0x13, 0x03, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x23, 0xbe, 0xb0, 0xa9, 0x6a, 0x6b, 0xa9, 0xb2, + 0xba, 0xa9, 0x73, 0x73, 0xa9, 0x01, 0x17, 0x01, 0x0b, 0xae, 0xae, 0xfe, 0xf5, 0xfe, 0xe9, 0xbb, 0xbb, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xff, 0x10, 0x02, 0x3b, 0x02, 0x22, 0x00, 0x1a, 0x00, 0x27, 0x40, 0x24, 0x1a, 0x13, 0x05, 0x03, + 0x03, 0x00, 0x12, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x62, + 0x00, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x25, 0x23, 0x19, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x11, 0x33, 0x13, 0x16, 0x16, + 0x17, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x37, 0x9f, 0x67, 0x07, 0x0d, 0x03, 0x04, 0x03, 0x0f, 0x07, 0x65, 0x9c, 0xe0, 0x22, 0x69, 0x61, 0x1a, + 0x25, 0x0d, 0x0a, 0x20, 0x11, 0x2e, 0x32, 0x0f, 0x0c, 0x02, 0x22, 0xfe, 0xc8, 0x16, 0x31, 0x16, 0x15, 0x32, 0x16, + 0x01, 0x38, 0xfd, 0xac, 0x5c, 0x62, 0x05, 0x03, 0x77, 0x02, 0x04, 0x35, 0x27, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x1e, + 0x00, 0x00, 0x01, 0xce, 0x02, 0x22, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x07, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, + 0x03, 0x02, 0x4c, 0x00, 0x01, 0x01, 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, + 0x00, 0x00, 0x6b, 0x00, 0x4e, 0x12, 0x11, 0x12, 0x10, 0x04, 0x0d, 0x1a, 0x2b, 0x21, 0x21, 0x35, 0x13, 0x23, 0x35, + 0x21, 0x15, 0x03, 0x33, 0x01, 0xce, 0xfe, 0x50, 0xfc, 0xee, 0x01, 0x99, 0xf5, 0xfe, 0x59, 0x01, 0x56, 0x73, 0x61, + 0xfe, 0xb3, 0x00, 0x01, 0x00, 0x0f, 0xff, 0x62, 0x01, 0x62, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x18, + 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x1b, 0x11, 0x16, 0x11, 0x16, 0x10, 0x06, + 0x0d, 0x1c, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x35, 0x34, 0x26, 0x23, 0x35, 0x32, 0x36, 0x35, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x15, 0x06, 0x06, 0x15, 0x15, 0x14, 0x07, 0x15, 0x16, 0x15, 0x15, 0x14, 0x16, 0x17, 0x01, 0x62, 0x55, + 0x5d, 0x24, 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5d, 0x55, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x9e, 0x1c, 0x3c, 0x30, + 0x9a, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9b, 0x30, 0x3c, 0x1c, 0x6e, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, + 0x5b, 0x92, 0x2a, 0x1a, 0x01, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x28, + 0x4b, 0xb0, 0x27, 0x50, 0x58, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, + 0x40, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0xb4, 0x11, 0x10, 0x02, 0x0d, + 0x18, 0x2b, 0x13, 0x33, 0x11, 0x23, 0xde, 0x6b, 0x6b, 0x02, 0xf5, 0xfc, 0x28, 0x00, 0x00, 0x01, 0x00, 0x28, 0xff, + 0x62, 0x01, 0x7b, 0x02, 0xca, 0x00, 0x1f, 0x00, 0x2c, 0x40, 0x29, 0x06, 0x01, 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, + 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x16, 0x11, 0x16, 0x11, 0x1b, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x17, 0x36, 0x36, 0x35, + 0x35, 0x34, 0x37, 0x35, 0x26, 0x35, 0x35, 0x34, 0x26, 0x27, 0x35, 0x32, 0x16, 0x16, 0x15, 0x15, 0x14, 0x16, 0x33, + 0x15, 0x22, 0x06, 0x15, 0x15, 0x14, 0x06, 0x06, 0x23, 0x28, 0x27, 0x2e, 0x72, 0x72, 0x2e, 0x27, 0x56, 0x5c, 0x24, + 0x40, 0x3d, 0x3d, 0x40, 0x24, 0x5c, 0x56, 0x30, 0x01, 0x1a, 0x2a, 0x92, 0x5b, 0x11, 0x06, 0x11, 0x5b, 0x92, 0x2a, + 0x1a, 0x01, 0x6e, 0x1c, 0x3c, 0x30, 0x9b, 0x2f, 0x28, 0x75, 0x28, 0x2f, 0x9a, 0x30, 0x3c, 0x1c, 0x00, 0x00, 0x01, + 0x00, 0x2b, 0x01, 0x0d, 0x02, 0x10, 0x01, 0xb4, 0x00, 0x17, 0x00, 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, + 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, + 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, + 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, + 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, + 0x26, 0x01, 0x0c, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, + 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, + 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x17, 0x01, 0xa0, 0x01, 0x57, 0x03, 0x56, 0x00, 0x17, 0x00, 0x30, 0x40, 0x2d, + 0x0c, 0x01, 0x01, 0x02, 0x0b, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x03, + 0x02, 0x01, 0x69, 0x00, 0x03, 0x00, 0x00, 0x03, 0x57, 0x00, 0x03, 0x03, 0x00, 0x5f, 0x00, 0x00, 0x03, 0x00, 0x4f, + 0x16, 0x24, 0x27, 0x10, 0x04, 0x0c, 0x1a, 0x2b, 0x01, 0x21, 0x35, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x33, 0x01, 0x57, 0xfe, 0xc4, 0x6d, 0x2d, + 0x21, 0x17, 0x14, 0x27, 0x31, 0x3c, 0x20, 0x4f, 0x35, 0x41, 0x4f, 0x32, 0x3b, 0x33, 0xac, 0x01, 0xa0, 0x52, 0x6b, + 0x2c, 0x2f, 0x1a, 0x12, 0x14, 0x2b, 0x4a, 0x1c, 0x23, 0x3f, 0x3b, 0x2d, 0x4a, 0x35, 0x2e, 0x00, 0x01, 0x00, 0x1a, + 0x01, 0x98, 0x01, 0x5e, 0x03, 0x55, 0x00, 0x26, 0x00, 0x4d, 0x40, 0x4a, 0x24, 0x01, 0x05, 0x00, 0x23, 0x01, 0x04, + 0x05, 0x05, 0x01, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x0e, 0x01, 0x01, 0x02, 0x05, 0x4c, 0x06, 0x01, 0x00, 0x00, + 0x05, 0x04, 0x00, 0x05, 0x69, 0x00, 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, + 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x01, 0x00, 0x21, 0x1f, 0x1b, 0x19, 0x18, 0x16, 0x13, + 0x11, 0x0c, 0x0a, 0x00, 0x26, 0x01, 0x26, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x07, 0x15, 0x16, + 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x23, 0x23, 0x35, 0x33, + 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0xb9, 0x49, 0x4e, 0x4d, 0x5b, 0x5d, 0x56, + 0x29, 0x49, 0x1e, 0x21, 0x48, 0x23, 0x4a, 0x24, 0x2f, 0x35, 0x2e, 0x2c, 0x23, 0x1c, 0x1b, 0x1a, 0x30, 0x1a, 0x31, + 0x1f, 0x4e, 0x03, 0x55, 0x3b, 0x30, 0x4e, 0x1b, 0x04, 0x15, 0x51, 0x3b, 0x44, 0x0f, 0x11, 0x5e, 0x14, 0x12, 0x32, + 0x16, 0x1a, 0x50, 0x1c, 0x16, 0x14, 0x18, 0x12, 0x13, 0x45, 0x17, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x20, 0x01, 0xa0, + 0x01, 0x15, 0x03, 0x4c, 0x00, 0x0d, 0x00, 0x27, 0x40, 0x24, 0x0c, 0x0b, 0x07, 0x03, 0x00, 0x01, 0x01, 0x4c, 0x02, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x57, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, + 0x00, 0x0d, 0x00, 0x0d, 0x11, 0x03, 0x0c, 0x17, 0x2b, 0x01, 0x11, 0x23, 0x35, 0x34, 0x36, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x01, 0x15, 0x70, 0x02, 0x02, 0x01, 0x07, 0x14, 0x0a, 0x2d, 0x38, 0x97, 0x03, 0x4c, 0xfe, + 0x54, 0xd6, 0x0d, 0x27, 0x25, 0x0a, 0x09, 0x14, 0x07, 0x24, 0x45, 0x76, 0x00, 0x01, 0xff, 0x40, 0x00, 0x00, 0x01, + 0x41, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x00, 0x00, 0x6b, + 0x00, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x01, 0x01, 0x23, 0x01, 0x01, 0x41, + 0xfe, 0x74, 0x75, 0x01, 0x8c, 0x02, 0xca, 0xfd, 0x36, 0x02, 0xca, 0x00, 0x02, 0x00, 0x0c, 0x01, 0xa0, 0x01, 0x73, + 0x03, 0x4f, 0x00, 0x0a, 0x00, 0x12, 0x00, 0x5e, 0x40, 0x0a, 0x0d, 0x01, 0x04, 0x03, 0x06, 0x01, 0x00, 0x04, 0x02, + 0x4c, 0x4b, 0xb0, 0x10, 0x50, 0x58, 0x40, 0x1e, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x00, 0x01, 0x71, + 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, + 0x1b, 0x40, 0x1d, 0x00, 0x03, 0x04, 0x03, 0x85, 0x00, 0x01, 0x00, 0x01, 0x86, 0x05, 0x01, 0x04, 0x00, 0x00, 0x04, + 0x57, 0x05, 0x01, 0x04, 0x04, 0x00, 0x60, 0x02, 0x01, 0x00, 0x04, 0x00, 0x50, 0x59, 0x40, 0x09, 0x17, 0x11, 0x12, + 0x11, 0x11, 0x10, 0x06, 0x0c, 0x1c, 0x2b, 0x01, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x13, 0x33, 0x11, 0x33, 0x27, + 0x34, 0x37, 0x06, 0x06, 0x07, 0x07, 0x33, 0x01, 0x73, 0x3d, 0x6f, 0xbb, 0xb6, 0x74, 0x3d, 0xac, 0x03, 0x05, 0x17, + 0x09, 0x3e, 0x60, 0x01, 0xef, 0x4f, 0x4f, 0x4c, 0x01, 0x14, 0xfe, 0xf3, 0x56, 0x26, 0x29, 0x0d, 0x2a, 0x0e, 0x60, + 0x00, 0x01, 0x00, 0x28, 0x01, 0x98, 0x01, 0x5d, 0x03, 0x4e, 0x00, 0x1d, 0x00, 0x42, 0x40, 0x3f, 0x1c, 0x03, 0x02, + 0x04, 0x01, 0x1b, 0x10, 0x02, 0x03, 0x04, 0x0f, 0x01, 0x02, 0x03, 0x03, 0x4c, 0x06, 0x01, 0x05, 0x00, 0x00, 0x01, + 0x05, 0x00, 0x67, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, 0x69, 0x00, 0x03, 0x02, 0x02, 0x03, 0x59, 0x00, 0x03, + 0x03, 0x02, 0x61, 0x00, 0x02, 0x03, 0x02, 0x51, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x23, 0x25, 0x24, 0x23, 0x11, + 0x07, 0x0c, 0x1b, 0x2b, 0x01, 0x15, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, 0x27, 0x37, 0x01, 0x40, 0xae, 0x07, + 0x0a, 0x1c, 0x11, 0x41, 0x5a, 0x5e, 0x58, 0x23, 0x44, 0x18, 0x19, 0x42, 0x1a, 0x26, 0x2d, 0x51, 0x0c, 0x22, 0x0b, + 0x36, 0x12, 0x03, 0x4e, 0x55, 0x48, 0x01, 0x04, 0x46, 0x42, 0x47, 0x4f, 0x0c, 0x0d, 0x5f, 0x10, 0x14, 0x1d, 0x23, + 0x3e, 0x05, 0x04, 0x14, 0xd9, 0x00, 0x00, 0x01, 0x00, 0x1d, 0x01, 0xa0, 0x01, 0x64, 0x03, 0x4c, 0x00, 0x06, 0x00, + 0x2a, 0x40, 0x27, 0x05, 0x01, 0x00, 0x01, 0x01, 0x4c, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, + 0x01, 0x57, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, + 0x11, 0x04, 0x0c, 0x18, 0x2b, 0x13, 0x13, 0x23, 0x35, 0x21, 0x15, 0x03, 0x4b, 0xa9, 0xd7, 0x01, 0x47, 0x9d, 0x01, + 0xa0, 0x01, 0x55, 0x57, 0x4a, 0xfe, 0x9e, 0x00, 0x00, 0x03, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x56, 0x00, + 0x17, 0x00, 0x22, 0x00, 0x2d, 0x00, 0x39, 0x40, 0x36, 0x23, 0x1d, 0x12, 0x06, 0x04, 0x03, 0x02, 0x01, 0x4c, 0x04, + 0x01, 0x00, 0x05, 0x01, 0x02, 0x03, 0x00, 0x02, 0x69, 0x00, 0x03, 0x01, 0x01, 0x03, 0x59, 0x00, 0x03, 0x03, 0x01, + 0x61, 0x00, 0x01, 0x03, 0x01, 0x51, 0x19, 0x18, 0x01, 0x00, 0x29, 0x27, 0x18, 0x22, 0x19, 0x22, 0x0d, 0x0b, 0x00, + 0x17, 0x01, 0x17, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, + 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x17, 0x36, + 0x36, 0x35, 0x34, 0x26, 0x07, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x35, 0x34, 0x26, 0x27, 0xbf, 0x3f, 0x58, 0x29, + 0x1d, 0x25, 0x31, 0x58, 0x4f, 0x58, 0x51, 0x2e, 0x1f, 0x1d, 0x21, 0x5a, 0x3f, 0x33, 0x1c, 0x18, 0x16, 0x1b, 0x17, + 0x24, 0x37, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x03, 0x56, 0x37, 0x37, 0x25, 0x2f, 0x11, 0x0f, 0x33, 0x2b, 0x36, 0x4a, + 0x49, 0x36, 0x2e, 0x2c, 0x10, 0x13, 0x32, 0x24, 0x36, 0x38, 0x4f, 0x27, 0x13, 0x1a, 0x0b, 0x0a, 0x19, 0x15, 0x0f, + 0x18, 0xb2, 0x17, 0x26, 0x18, 0x1b, 0x30, 0x16, 0x1c, 0x0a, 0x00, 0x02, 0x00, 0x14, 0x01, 0x96, 0x01, 0x67, 0x03, + 0x56, 0x00, 0x0b, 0x00, 0x13, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, + 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x0d, 0x0c, + 0x01, 0x00, 0x11, 0x0f, 0x0c, 0x13, 0x0d, 0x13, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0c, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x27, 0x32, 0x35, 0x34, 0x23, 0x22, 0x15, 0x14, + 0xbc, 0x52, 0x56, 0x50, 0x58, 0x54, 0x57, 0x52, 0x58, 0x2f, 0x2f, 0x2e, 0x01, 0x96, 0x77, 0x6a, 0x6a, 0x75, 0x75, + 0x6a, 0x6a, 0x77, 0x65, 0x7b, 0x7a, 0x7a, 0x7b, 0x00, 0x02, 0x00, 0x16, 0x01, 0x96, 0x01, 0x66, 0x03, 0x55, 0x00, + 0x1b, 0x00, 0x26, 0x00, 0x4a, 0x40, 0x47, 0x03, 0x01, 0x01, 0x00, 0x04, 0x01, 0x02, 0x01, 0x0a, 0x01, 0x04, 0x02, + 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x69, 0x00, 0x02, 0x07, 0x01, 0x04, 0x05, 0x02, 0x04, + 0x69, 0x00, 0x05, 0x03, 0x03, 0x05, 0x59, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x05, 0x03, 0x51, 0x1d, 0x1c, + 0x01, 0x00, 0x23, 0x21, 0x1c, 0x26, 0x1d, 0x26, 0x15, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x08, + 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x17, 0x15, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x17, 0x22, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, + 0x35, 0x34, 0x26, 0x01, 0x03, 0x0e, 0x27, 0x0d, 0x0c, 0x1f, 0x14, 0x46, 0x39, 0x03, 0x05, 0x0e, 0x2f, 0x26, 0x38, + 0x42, 0x56, 0x4b, 0x4c, 0x63, 0x13, 0x33, 0x5d, 0x08, 0x1f, 0x21, 0x1d, 0x1f, 0x3b, 0x1d, 0x03, 0x55, 0x03, 0x03, + 0x57, 0x02, 0x04, 0x42, 0x35, 0x14, 0x19, 0x44, 0x41, 0x47, 0x52, 0x60, 0x60, 0x2f, 0x5b, 0x49, 0x2c, 0xea, 0x22, + 0x14, 0x1a, 0x30, 0x43, 0x1d, 0x20, 0x00, 0x02, 0x00, 0x15, 0x01, 0x96, 0x01, 0x64, 0x03, 0x56, 0x00, 0x19, 0x00, + 0x24, 0x00, 0x4a, 0x40, 0x47, 0x10, 0x01, 0x03, 0x05, 0x0b, 0x01, 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, + 0x06, 0x01, 0x00, 0x07, 0x01, 0x04, 0x05, 0x00, 0x04, 0x69, 0x00, 0x05, 0x00, 0x03, 0x02, 0x05, 0x03, 0x69, 0x00, + 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x02, 0x01, 0x51, 0x1b, 0x1a, 0x01, 0x00, + 0x20, 0x1e, 0x1a, 0x24, 0x1b, 0x24, 0x15, 0x13, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0c, 0x16, + 0x2b, 0x13, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x23, + 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x17, 0x22, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0xb8, 0x4a, 0x62, 0x28, 0x62, 0x58, 0x16, 0x2a, 0x0c, 0x19, 0x30, 0x3f, 0x35, 0x03, 0x05, 0x0e, 0x2d, 0x25, 0x3a, + 0x42, 0x57, 0x51, 0x3a, 0x1b, 0x1b, 0x1f, 0x22, 0x1e, 0x03, 0x56, 0x5f, 0x60, 0x46, 0x75, 0x46, 0x04, 0x04, 0x58, + 0x08, 0x43, 0x34, 0x14, 0x19, 0x45, 0x41, 0x46, 0x52, 0x54, 0x43, 0x1d, 0x21, 0x22, 0x14, 0x1d, 0x2e, 0xff, 0xff, + 0x00, 0x14, 0x00, 0x00, 0x03, 0x32, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x47, 0x01, + 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x02, 0x6a, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4a, 0x01, 0x82, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x02, 0x63, 0x02, 0xfd, 0x00, + 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x83, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, + 0x03, 0xec, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x82, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x4a, 0x03, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x14, 0x00, 0x00, 0x03, 0xe6, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x47, 0x00, 0x00, 0x00, 0x27, 0x00, 0x47, 0x01, 0x83, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x03, 0x06, 0x00, + 0x00, 0xff, 0xff, 0x00, 0x14, 0xff, 0xf6, 0x01, 0x67, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x01, + 0x15, 0x01, 0xac, 0x03, 0x07, 0x00, 0x62, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x17, 0x00, 0x00, 0x01, 0x57, 0x01, 0xb6, 0x01, 0x07, 0x00, 0x60, 0x00, + 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, + 0xff, 0xf8, 0x01, 0x5e, 0x01, 0xb5, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, + 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x73, 0x01, 0xaf, 0x03, 0x07, + 0x00, 0x64, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x28, 0xff, 0xf8, 0x01, 0x5d, 0x01, 0xae, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, 0x01, 0x66, 0x01, + 0xb5, 0x03, 0x07, 0x00, 0x69, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x64, 0x01, 0xac, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xfe, + 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0xff, 0xf6, + 0x01, 0x66, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, + 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x15, 0xff, 0xf6, 0x01, 0x64, 0x01, 0xb6, 0x03, 0x07, 0x00, 0x6a, + 0x00, 0x00, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x14, 0x01, 0x14, 0x01, 0x67, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x68, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x20, 0x01, 0x1e, 0x01, 0x15, 0x02, 0xca, 0x03, + 0x07, 0x00, 0x62, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x17, 0x01, 0x1e, 0x01, 0x57, 0x02, 0xd4, 0x01, 0x07, 0x00, 0x60, 0x00, 0x00, 0xff, 0x7e, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1a, 0x01, 0x16, 0x01, 0x5e, + 0x02, 0xd3, 0x03, 0x07, 0x00, 0x61, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x01, 0x1e, 0x01, 0x73, 0x02, 0xcd, 0x03, 0x07, 0x00, 0x64, 0x00, 0x00, + 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x28, 0x01, + 0x16, 0x01, 0x5d, 0x02, 0xcc, 0x03, 0x07, 0x00, 0x65, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, + 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd3, 0x03, 0x07, 0x00, + 0x69, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x1d, 0x01, 0x1e, 0x01, 0x64, 0x02, 0xca, 0x03, 0x07, 0x00, 0x66, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, + 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x16, 0x01, 0x14, 0x01, 0x66, 0x02, 0xd4, + 0x03, 0x07, 0x00, 0x67, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0x00, 0x15, 0x01, 0x14, 0x01, 0x64, 0x02, 0xd4, 0x03, 0x07, 0x00, 0x6a, 0x00, 0x00, 0xff, 0x7e, + 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x84, 0x00, 0xd4, 0x00, 0x18, 0x00, 0x65, 0x00, 0x06, 0x00, 0x02, 0x00, 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, + 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x54, 0x00, + 0xa8, 0x01, 0x0f, 0x01, 0xc7, 0x02, 0x5a, 0x02, 0x75, 0x02, 0x99, 0x02, 0xbd, 0x02, 0xed, 0x03, 0x15, 0x03, 0x35, + 0x03, 0x50, 0x03, 0x6f, 0x03, 0x8b, 0x03, 0xc4, 0x03, 0xeb, 0x04, 0x30, 0x04, 0x8f, 0x04, 0xc8, 0x05, 0x1a, 0x05, + 0x90, 0x05, 0xb5, 0x06, 0x21, 0x06, 0x82, 0x06, 0xb7, 0x06, 0xe9, 0x06, 0xff, 0x07, 0x2a, 0x07, 0x40, 0x07, 0x96, + 0x08, 0x40, 0x08, 0x7a, 0x08, 0xd0, 0x09, 0x16, 0x09, 0x45, 0x09, 0x70, 0x09, 0x94, 0x09, 0xe4, 0x0a, 0x0c, 0x0a, + 0x34, 0x0a, 0x67, 0x0a, 0x93, 0x0a, 0xb1, 0x0a, 0xec, 0x0b, 0x1c, 0x0b, 0x58, 0x0b, 0x93, 0x0b, 0xdb, 0x0c, 0x1e, + 0x0c, 0x71, 0x0c, 0x8f, 0x0c, 0xbc, 0x0c, 0xeb, 0x0d, 0x3f, 0x0d, 0x69, 0x0d, 0x8d, 0x0d, 0xb8, 0x0d, 0xd7, 0x0d, + 0xf3, 0x0e, 0x12, 0x0e, 0x38, 0x0e, 0x55, 0x0e, 0x80, 0x0e, 0xf9, 0x0f, 0x61, 0x0f, 0xa8, 0x10, 0x1d, 0x10, 0x6d, + 0x10, 0xd7, 0x11, 0x67, 0x11, 0x9f, 0x11, 0xd2, 0x12, 0x1b, 0x12, 0x4e, 0x12, 0x63, 0x12, 0xd0, 0x13, 0x1f, 0x13, + 0x58, 0x13, 0xcc, 0x14, 0x3b, 0x14, 0x92, 0x14, 0xe4, 0x15, 0x2b, 0x15, 0x76, 0x15, 0xa3, 0x15, 0xf5, 0x16, 0x1e, + 0x16, 0x5f, 0x16, 0x88, 0x16, 0xcc, 0x16, 0xed, 0x17, 0x31, 0x17, 0x76, 0x17, 0xb5, 0x18, 0x13, 0x18, 0x42, 0x18, + 0x5e, 0x18, 0xae, 0x18, 0xfd, 0x19, 0x24, 0x19, 0x84, 0x19, 0xbc, 0x1a, 0x1a, 0x1a, 0x75, 0x1a, 0x81, 0x1a, 0x8d, + 0x1a, 0x99, 0x1a, 0xa9, 0x1a, 0xb9, 0x1a, 0xc8, 0x1a, 0xd7, 0x1a, 0xe6, 0x1a, 0xf5, 0x1b, 0x04, 0x1b, 0x13, 0x1b, + 0x22, 0x1b, 0x31, 0x1b, 0x40, 0x1b, 0x4f, 0x1b, 0x5e, 0x1b, 0x6d, 0x1b, 0x7c, 0x1b, 0x8b, 0x1b, 0x9a, 0x1b, 0xa9, + 0x1b, 0xb8, 0x1b, 0xc7, 0x1b, 0xd6, 0x1b, 0xe5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0x28, + 0x5e, 0xd5, 0x8c, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xd3, 0xe7, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc1, 0x01, 0xfd, 0x7c, 0xfe, 0x7b, 0x0a, 0xf1, 0x04, 0x2d, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x59, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1a, + 0x00, 0x36, 0x01, 0xdf, 0x00, 0x3d, 0x02, 0x86, 0x00, 0x16, 0x02, 0x3c, 0x00, 0x2b, 0x03, 0x86, 0x00, 0x1e, 0x02, + 0xee, 0x00, 0x28, 0x01, 0x0a, 0x00, 0x3d, 0x01, 0x53, 0x00, 0x28, 0x01, 0x53, 0x00, 0x1e, 0x02, 0x1e, 0x00, 0x1d, + 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x1d, 0x00, 0x1f, 0x01, 0x40, 0x00, 0x1c, 0x01, 0x19, 0x00, 0x36, 0x01, 0x9f, 0x00, + 0x07, 0x02, 0x3c, 0x00, 0x24, 0x02, 0x3c, 0x00, 0x3b, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, 0x00, 0x26, 0x02, 0x3c, + 0x00, 0x11, 0x02, 0x3c, 0x00, 0x31, 0x02, 0x3c, 0x00, 0x23, 0x02, 0x3c, 0x00, 0x1b, 0x02, 0x3c, 0x00, 0x23, 0x02, + 0x3c, 0x00, 0x20, 0x01, 0x19, 0x00, 0x36, 0x01, 0x1d, 0x00, 0x1f, 0x02, 0x3c, 0x00, 0x2b, 0x02, 0x3c, 0x00, 0x2b, + 0x02, 0x3c, 0x00, 0x2b, 0x01, 0xdd, 0x00, 0x05, 0x03, 0x82, 0x00, 0x2f, 0x02, 0xb4, 0x00, 0x00, 0x02, 0x99, 0x00, + 0x55, 0x02, 0x82, 0x00, 0x37, 0x02, 0xdc, 0x00, 0x55, 0x02, 0x30, 0x00, 0x5a, 0x02, 0x25, 0x00, 0x5a, 0x02, 0xd4, + 0x00, 0x3a, 0x02, 0xfd, 0x00, 0x5a, 0x01, 0x85, 0x00, 0x20, 0x01, 0x4b, 0xff, 0xb6, 0x02, 0x98, 0x00, 0x5a, 0x02, + 0x2f, 0x00, 0x55, 0x03, 0xaf, 0x00, 0x5a, 0x03, 0x2d, 0x00, 0x5a, 0x03, 0x17, 0x00, 0x37, 0x02, 0x6d, 0x00, 0x55, + 0x03, 0x17, 0x00, 0x37, 0x02, 0x90, 0x00, 0x55, 0x02, 0x27, 0x00, 0x2e, 0x02, 0x41, 0x00, 0x13, 0x02, 0xf4, 0x00, + 0x55, 0x02, 0x8a, 0x00, 0x00, 0x03, 0xc7, 0x00, 0x00, 0x02, 0x9e, 0x00, 0x03, 0x02, 0x72, 0x00, 0x00, 0x02, 0x43, + 0x00, 0x18, 0x01, 0x4b, 0x00, 0x46, 0x01, 0x9f, 0x00, 0x06, 0x01, 0x4b, 0x00, 0x19, 0x02, 0x3c, 0x00, 0x17, 0x01, + 0x9b, 0xff, 0xfe, 0x01, 0x6d, 0x00, 0x28, 0x02, 0x57, 0x00, 0x28, 0x02, 0x78, 0x00, 0x49, 0x02, 0x04, 0x00, 0x2f, + 0x02, 0x78, 0x00, 0x2f, 0x02, 0x55, 0x00, 0x2f, 0x01, 0x83, 0x00, 0x14, 0x02, 0x78, 0x00, 0x2f, 0x02, 0x8a, 0x00, + 0x49, 0x01, 0x2b, 0x00, 0x44, 0x01, 0x2a, 0xff, 0xcb, 0x02, 0x6c, 0x00, 0x4e, 0x01, 0x2a, 0x00, 0x49, 0x03, 0xcf, + 0x00, 0x49, 0x02, 0x8a, 0x00, 0x49, 0x02, 0x71, 0x00, 0x2f, 0x02, 0x78, 0x00, 0x49, 0x02, 0x78, 0x00, 0x2f, 0x01, + 0xbf, 0x00, 0x49, 0x01, 0xf6, 0x00, 0x2e, 0x01, 0xb2, 0x00, 0x17, 0x02, 0x8a, 0x00, 0x46, 0x02, 0x3b, 0x00, 0x00, + 0x03, 0x58, 0x00, 0x0a, 0x02, 0x42, 0x00, 0x05, 0x02, 0x3b, 0x00, 0x00, 0x01, 0xed, 0x00, 0x1e, 0x01, 0x8a, 0x00, + 0x0f, 0x02, 0x27, 0x00, 0xde, 0x01, 0x8a, 0x00, 0x28, 0x02, 0x3c, 0x00, 0x2b, 0x01, 0x7b, 0x00, 0x17, 0x01, 0x7c, + 0x00, 0x1a, 0x01, 0x7c, 0x00, 0x20, 0x00, 0x82, 0xff, 0x40, 0x01, 0x7c, 0x00, 0x0c, 0x01, 0x7c, 0x00, 0x28, 0x01, + 0x7c, 0x00, 0x1d, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7b, 0x00, 0x14, 0x01, 0x7c, 0x00, 0x16, 0x01, 0x7c, 0x00, 0x15, + 0x03, 0x04, 0x00, 0x14, 0x02, 0xad, 0x00, 0x14, 0x02, 0xb4, 0x00, 0x14, 0x04, 0x2f, 0x00, 0x14, 0x04, 0x37, 0x00, + 0x14, 0x01, 0x7c, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, 0x1d, + 0x00, 0x16, 0x00, 0x15, 0x00, 0x14, 0x00, 0x20, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x0c, 0x00, 0x28, 0x00, 0x16, 0x00, + 0x1d, 0x00, 0x16, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x0b, 0x17, + 0xfd, 0x7c, 0xfd, 0x8d, 0x0a, 0xf1, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x04, 0x02, 0x6a, 0x02, 0xbc, 0x00, 0x05, 0x00, 0x00, 0x02, 0x8a, 0x02, 0x58, + 0x00, 0x00, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x32, 0x01, 0x48, 0x00, 0x00, 0x02, + 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x00, 0xa0, 0x00, 0x20, 0x00, 0x7e, 0x04, 0x2d, 0xfe, + 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x02, 0xca, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, 0xb8, 0x00, 0x0e, 0x51, 0x4b, + 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, 0x8a, 0x55, 0x58, 0xb0, 0x02, + 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, 0xb0, 0x00, 0x59, 0xb0, 0x00, + 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, 0xb0, 0x20, 0x60, 0x66, 0x2d, + 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, 0x03, 0x14, 0x15, 0x00, 0x42, + 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, 0x25, 0x03, 0x43, 0xb0, 0x02, + 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, 0x04, 0x50, 0x78, 0xb2, 0x02, + 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, 0xb2, 0x0e, 0x15, 0x01, 0x42, + 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, 0x03, 0x2b, 0xb0, 0x15, 0x43, + 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x1b, 0x20, 0x64, + 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0xb0, 0x06, 0x45, + 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, 0x58, 0x20, 0xb0, 0x50, 0x50, + 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, 0x59, 0x59, 0x20, 0xb1, 0x01, + 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, + 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, 0x58, 0x20, 0x66, 0x20, 0x8a, + 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x0a, 0x60, 0x1b, + 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, 0x1b, 0xb0, 0x02, 0x25, 0xb0, + 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x21, 0xb0, 0x0c, 0x43, 0x1b, + 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, 0xb0, 0x0c, 0x43, 0x63, 0xb8, + 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, + 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, 0x20, 0x45, 0x20, 0xb0, 0x04, + 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, 0x08, 0x23, 0x42, 0x1b, 0x21, + 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x03, 0x2b, 0x20, 0x64, 0xb1, + 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, + 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, 0xb0, 0x08, 0x43, 0x20, 0x8a, + 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, 0x60, 0x50, 0x1b, 0x61, 0x52, + 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, 0x1b, 0x21, 0xb0, 0x40, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, 0x2b, 0xb2, 0x00, 0x02, 0x00, + 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, 0x00, 0x23, 0x42, 0x61, 0xb0, + 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, 0x09, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, 0x0e, 0x00, 0x43, 0x45, 0x42, + 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, + 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, + 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, 0xb0, 0x20, 0x50, 0x58, 0x21, + 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0d, 0x2c, 0x20, 0x20, 0x45, + 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, + 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, + 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, 0x00, 0x23, 0x42, 0xb3, 0x0d, + 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, 0xb0, 0x0f, 0x2c, 0xb1, 0x02, + 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, 0x20, 0xb0, 0x0f, 0x43, 0x4a, + 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, 0xb0, 0x00, 0x52, 0x58, 0x20, + 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb8, + 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, 0xb0, 0x11, 0x23, 0x42, 0x23, + 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, 0x0d, 0x65, 0x23, 0x78, 0x2d, + 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x1b, 0x21, 0x59, 0x24, 0xb0, + 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, 0xb1, 0x12, 0x12, 0x43, 0xb0, + 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, 0xb1, 0x0f, 0x02, 0x25, 0x42, + 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, 0x58, 0xb1, 0x01, 0x00, 0x43, + 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x23, 0xb0, 0x01, 0x61, + 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x02, 0x25, 0x42, 0xb0, + 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, 0x43, 0x47, 0x60, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x20, 0xb0, 0x0e, 0x43, 0x63, + 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb1, + 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, 0x01, 0x43, 0x60, 0x42, 0x2d, + 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, + 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x13, 0x00, + 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, + 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, 0x17, 0x2c, 0xb1, 0x01, 0x15, + 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, 0x03, 0x15, 0x2b, 0x2d, 0xb0, + 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, + 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, 0x2c, 0xb1, 0x08, 0x15, 0x2b, + 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, 0x1b, 0x21, 0x21, 0x59, 0x2d, + 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, 0x60, 0x4b, 0x54, 0x58, 0x23, + 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x72, 0x1b, 0x21, 0x21, 0x59, + 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, 0x20, + 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb0, 0x01, 0x61, 0xb5, 0x18, + 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, + 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, 0x20, 0x2b, 0x2d, 0xb0, 0x23, + 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, 0xb0, 0x25, 0x2c, 0xb1, 0x04, + 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, 0xb1, 0x06, 0x20, 0x2b, 0x2d, + 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, + 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x2f, 0x2c, 0x20, 0x60, + 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x01, 0x60, 0xb0, 0x2e, + 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, 0x31, 0x2c, 0x20, 0x20, 0x47, + 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, + 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, + 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, + 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, + 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, + 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, + 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, 0xb1, 0x0e, 0x06, 0x45, 0x42, + 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, + 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, 0x3c, 0x2d, 0xb0, 0x38, 0x2c, + 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, 0x43, 0x63, 0x38, 0x2d, 0xb0, + 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb0, 0x02, 0x25, 0x49, + 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, 0x01, 0x23, 0x42, 0xb2, 0x38, + 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, + 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x65, 0x8a, 0x2e, + 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x04, + 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, + 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, + 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x8a, 0x23, 0x47, + 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, + 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, + 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, + 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, 0x23, 0xb0, 0x0a, 0x43, 0x46, + 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x20, 0xb0, 0x01, 0x2b, + 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, 0x25, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, 0x26, 0x61, 0x20, 0xb0, 0x04, + 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x23, 0x20, 0x20, + 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, + 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x3c, 0x38, 0x2d, 0xb0, 0x3d, + 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, + 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0xb0, 0x03, + 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, 0x20, 0x3c, 0x23, 0x21, 0x1b, + 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, 0x25, 0xb0, 0x04, 0x25, 0x47, + 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, + 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x23, + 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x43, 0x20, 0x2e, + 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x40, 0x2c, 0x23, + 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, + 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, + 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, + 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, 0xb0, 0x3a, 0x2b, 0x23, 0x20, + 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, + 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, + 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, 0x46, 0x23, 0x47, 0x61, 0xb0, + 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, 0x20, 0x3c, 0x20, 0x2e, 0x23, + 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, 0x42, 0xb0, 0x00, 0x16, 0xb0, + 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, 0x23, 0x42, 0xb1, 0x0c, + 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, 0x58, 0xb3, 0x04, 0x20, + 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, 0xb0, 0x06, 0x43, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, + 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, + 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, 0x61, 0x38, 0x23, 0x20, 0x3c, + 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x21, 0x59, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, + 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x23, 0x38, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, + 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, + 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, + 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, 0xb0, 0x4c, 0x2c, 0xb0, 0x39, + 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, 0x8a, 0x23, 0x61, 0x38, 0xb1, + 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, + 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x51, 0x2c, 0xb2, + 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, 0xb0, 0x53, 0x2c, 0xb2, 0x00, + 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x55, 0x2c, 0xb2, 0x01, 0x00, + 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, 0x2c, 0xb3, 0x00, 0x00, 0x00, + 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x59, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5b, 0x2c, 0xb3, 0x00, + 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, + 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, + 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x61, 0x2c, 0xb2, + 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, 0xb0, 0x63, 0x2c, 0xb2, 0x00, + 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x65, 0x2c, 0xb2, 0x01, 0x00, + 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, 0x2c, 0xb3, 0x00, 0x00, 0x00, + 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x69, 0x2c, 0xb3, 0x01, 0x00, + 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6b, 0x2c, 0xb3, 0x00, + 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, + 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, + 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x72, 0x2c, 0xb0, 0x00, + 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, + 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, 0x2c, 0xb0, 0x00, 0x16, 0xb1, + 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, + 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x78, 0x2c, 0xb1, 0x00, 0x3d, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, + 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0x2e, + 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7f, + 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, + 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, + 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x84, 0x2c, 0xb1, + 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x87, 0x2c, 0xb1, 0x00, 0x3f, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x89, 0x2c, + 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, + 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, 0x04, 0x02, 0x03, 0x45, 0x58, + 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, 0x50, 0x78, 0xb1, 0x05, 0x01, + 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb0, + 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, 0x93, 0x83, 0x73, 0x00, 0x5d, + 0x51, 0x41, 0x00, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, 0x08, 0x78, 0x08, 0x68, 0x08, + 0x62, 0x02, 0x56, 0x06, 0x46, 0x08, 0x3a, 0x06, 0x32, 0x04, 0x24, 0x07, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x07, 0x42, + 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x4e, 0x06, 0x40, 0x04, 0x36, 0x02, 0x2b, + 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, 0x1a, 0x40, 0x18, 0xc0, 0x15, + 0xc0, 0x11, 0xc0, 0x0e, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb1, 0x00, 0x19, 0x42, 0x41, + 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, 0x88, 0x51, 0x58, 0xb0, 0x40, + 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, 0xb8, 0x08, 0x00, 0x88, 0x58, + 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, 0xba, 0x08, 0x80, 0x00, 0x01, + 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, 0x59, 0x59, 0x59, 0x40, 0x14, + 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x48, 0x06, 0x3c, 0x04, 0x34, 0x02, 0x26, 0x05, 0x09, + 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, 0x05, 0x64, 0x06, 0x00, 0x44, + 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x98, + 0x00, 0x72, 0x00, 0x72, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd4, 0xff, 0xf6, 0x02, + 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x00, 0x00, 0x02, 0x50, + 0xff, 0xf8, 0x00, 0x95, 0x00, 0x95, 0x00, 0x73, 0x00, 0x73, 0x02, 0x48, 0x02, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x50, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0xff, 0xf6, + 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, + 0x10, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x68, + 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x7b, 0x00, 0x7b, 0x00, 0x65, 0x00, 0x65, 0x01, 0x1f, 0x01, 0x1f, 0x00, + 0x9a, 0x00, 0x9a, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, + 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, + 0x45, 0x01, 0x2c, 0xff, 0x7e, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, 0x34, 0xff, 0x74, 0x01, 0x68, + 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x64, 0x00, 0x64, 0x00, 0x45, 0x00, 0x45, 0x02, 0xcb, 0x01, 0xa0, 0x02, + 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe7, 0x01, 0x96, 0x02, 0xe7, 0x02, 0x6d, 0x01, 0x19, 0x00, 0x8f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, + 0x00, 0x08, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x30, 0x00, 0xd0, 0x00, 0x03, 0x00, + 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x54, + 0x01, 0x1c, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x1a, 0x01, 0x70, 0x00, 0x43, 0x00, 0x6f, 0x00, + 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, + 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x6f, 0x00, + 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, + 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x73, 0x00, 0x20, 0x00, + 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x2f, 0x00, 0x67, + 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, + 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, + 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x67, 0x00, 0x72, 0x00, + 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, + 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, + 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, + 0x00, 0x6c, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, + 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, + 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, + 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, + 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, + 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, + 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, + 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x01, 0x00, 0x22, 0x00, 0x3b, 0x00, + 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x05, 0x00, 0x18, + 0x00, 0x18, 0x00, 0x20, 0x00, 0x28, 0x00, 0x36, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6b, 0x00, 0x6f, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x56, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x5a, 0x00, 0x02, 0x00, 0x06, + 0x00, 0x0a, 0x00, 0x01, 0x01, 0x65, 0x00, 0x01, 0x02, 0xca, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, + 0x68, 0x00, 0x01, 0x02, 0xcf, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, 0x46, + 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, + 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0x65, + 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x07, 0x2c, 0x00, + 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0xf6, 0x00, 0x01, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x62, 0x00, 0xe2, 0x00, 0x74, 0x00, 0x7a, 0x00, 0xb2, 0x00, 0x84, 0x00, 0x8a, 0x00, 0xb2, 0x00, 0xa8, 0x00, + 0xb2, 0x00, 0xb8, 0x00, 0xdc, 0x00, 0xdc, 0x00, 0xc2, 0x00, 0xe2, 0x00, 0xcc, 0x00, 0xd2, 0x00, 0xdc, 0x00, 0xdc, + 0x00, 0xdc, 0x00, 0xe2, 0x00, 0x01, 0x00, 0x15, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, 0x00, 0x23, 0x00, 0x25, 0x00, + 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3c, + 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, + 0x37, 0xff, 0xec, 0x00, 0x38, 0xff, 0xec, 0x00, 0x3a, 0xff, 0xe2, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x32, 0x00, 0x02, + 0x00, 0x0d, 0xff, 0xf6, 0x00, 0x0f, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x07, 0x00, 0x0a, 0x00, + 0x14, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x3e, + 0x00, 0x14, 0x00, 0x5e, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xf6, 0x00, 0x39, 0xff, 0xec, 0x00, 0x01, 0x00, + 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, + 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x5f, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, + 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, + 0x04, 0x32, 0x00, 0x04, 0x00, 0x00, 0x04, 0x86, 0x05, 0x50, 0x00, 0x17, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xba, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, + 0xff, 0xe2, 0xff, 0xce, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xc4, 0xff, 0xce, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xec, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, 0xff, 0xec, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, + 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xba, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0xff, 0xc4, 0xff, 0xba, 0xff, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x60, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x03, 0x00, 0x08, 0x00, 0x09, 0x00, + 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x2c, 0x00, 0x2d, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, + 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x50, 0x00, 0x51, + 0x00, 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6b, 0x00, 0x02, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, + 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, + 0x22, 0x00, 0x22, 0x00, 0x02, 0x00, 0x24, 0x00, 0x24, 0x00, 0x08, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x26, + 0x00, 0x26, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x09, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, + 0x00, 0x0c, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x0a, 0x00, 0x39, 0x00, 0x39, 0x00, + 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x07, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0e, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, + 0x00, 0x42, 0x00, 0x42, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x49, 0x00, 0x49, 0x00, 0x01, 0x00, + 0x4e, 0x00, 0x4f, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, 0x00, 0x55, 0x00, 0x0d, 0x00, 0x57, + 0x00, 0x58, 0x00, 0x05, 0x00, 0x59, 0x00, 0x59, 0x00, 0x16, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x05, 0x00, 0x5c, 0x00, + 0x5c, 0x00, 0x13, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x15, 0x00, 0x01, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x13, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x12, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x0b, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, + 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, + 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x36, 0x00, 0x6c, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, + 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1a, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x1a, 0x66, 0x72, 0x61, 0x63, 0x00, 0x20, 0x6c, 0x69, 0x67, 0x61, 0x00, 0x2a, 0x6e, + 0x75, 0x6d, 0x72, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x32, 0x00, + 0x10, 0x00, 0x1e, 0x00, 0x32, 0x00, 0x4a, 0x00, 0x88, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x28, 0x00, 0x5f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, + 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x69, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x2a, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00, 0x70, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, 0x7a, 0x00, + 0x83, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x36, 0x00, 0x01, 0x00, 0x08, + 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6f, 0x00, 0x03, 0x00, 0x47, 0x00, + 0x4d, 0x00, 0x6e, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x6d, 0x00, 0x02, + 0x00, 0x4d, 0x00, 0x6b, 0x00, 0x02, 0x00, 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x47}; + + constexpr unsigned char BOLD_ITALICS_DATA[] = { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x04, 0x00, 0x10, 0x47, 0x44, 0x45, 0x46, 0x0a, 0x6b, 0x06, + 0xbf, 0x00, 0x00, 0x5a, 0xd0, 0x00, 0x00, 0x00, 0x7e, 0x47, 0x50, 0x4f, 0x53, 0x33, 0x4f, 0x0e, 0xbf, 0x00, 0x00, + 0x5b, 0x50, 0x00, 0x00, 0x07, 0x4e, 0x47, 0x53, 0x55, 0x42, 0xfc, 0xd3, 0xd8, 0xce, 0x00, 0x00, 0x62, 0xa0, 0x00, + 0x00, 0x01, 0xd4, 0x4f, 0x53, 0x2f, 0x32, 0x6a, 0x82, 0x62, 0xb3, 0x00, 0x00, 0x47, 0xbc, 0x00, 0x00, 0x00, 0x60, + 0x63, 0x6d, 0x61, 0x70, 0x00, 0x0c, 0x00, 0xd1, 0x00, 0x00, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x63, 0x76, 0x74, + 0x20, 0x41, 0x2b, 0x1e, 0x46, 0x00, 0x00, 0x57, 0x64, 0x00, 0x00, 0x01, 0x2c, 0x66, 0x70, 0x67, 0x6d, 0x62, 0x2f, + 0x0b, 0x83, 0x00, 0x00, 0x48, 0x50, 0x00, 0x00, 0x0e, 0x0c, 0x67, 0x61, 0x73, 0x70, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x5a, 0xc8, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66, 0xb2, 0xab, 0x07, 0x57, 0x00, 0x00, 0x01, 0x1c, + 0x00, 0x00, 0x43, 0x06, 0x68, 0x65, 0x61, 0x64, 0x28, 0x3b, 0xd8, 0x55, 0x00, 0x00, 0x45, 0x5c, 0x00, 0x00, 0x00, + 0x36, 0x68, 0x68, 0x65, 0x61, 0x0d, 0x3d, 0x0b, 0xc5, 0x00, 0x00, 0x47, 0x98, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, + 0x74, 0x78, 0xfa, 0xcf, 0x0a, 0x08, 0x00, 0x00, 0x45, 0x94, 0x00, 0x00, 0x02, 0x02, 0x6c, 0x6f, 0x63, 0x61, 0xde, + 0x29, 0xcd, 0xbc, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00, 0x01, 0x16, 0x6d, 0x61, 0x78, 0x70, 0x03, 0x5b, 0x10, 0x44, + 0x00, 0x00, 0x44, 0x24, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x7e, 0x45, 0xc4, 0x00, 0x00, 0x58, + 0x90, 0x00, 0x00, 0x02, 0x18, 0x70, 0x6f, 0x73, 0x74, 0xff, 0x93, 0x00, 0x32, 0x00, 0x00, 0x5a, 0xa8, 0x00, 0x00, + 0x00, 0x20, 0x70, 0x72, 0x65, 0x70, 0xff, 0x8d, 0x0b, 0xc2, 0x00, 0x00, 0x56, 0x5c, 0x00, 0x00, 0x01, 0x05, 0x00, + 0x02, 0x00, 0x0b, 0xff, 0xf3, 0x01, 0x3e, 0x02, 0xca, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x2c, 0x40, 0x29, 0x04, 0x01, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, + 0x02, 0x4e, 0x05, 0x04, 0x00, 0x00, 0x0b, 0x09, 0x04, 0x0f, 0x05, 0x0f, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, + 0x17, 0x2b, 0x37, 0x13, 0x33, 0x03, 0x07, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x43, + 0x52, 0xa9, 0x7d, 0x69, 0x2a, 0x23, 0x32, 0x34, 0x23, 0x27, 0x36, 0xe8, 0x01, 0xe2, 0xfe, 0x1e, 0xf5, 0x27, 0x1b, + 0x2a, 0x3c, 0x24, 0x20, 0x2e, 0x36, 0x00, 0x02, 0x00, 0x62, 0x01, 0xc8, 0x01, 0xd2, 0x02, 0xca, 0x00, 0x03, 0x00, + 0x07, 0x00, 0x24, 0x40, 0x21, 0x05, 0x03, 0x04, 0x03, 0x01, 0x01, 0x00, 0x5f, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x01, + 0x4e, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, + 0x2b, 0x01, 0x13, 0x33, 0x03, 0x21, 0x13, 0x33, 0x03, 0x01, 0x27, 0x24, 0x87, 0x4a, 0xfe, 0xda, 0x23, 0x87, 0x4a, + 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x01, 0x02, 0xfe, 0xfe, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x02, 0x8b, 0x02, + 0xca, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x47, 0x40, 0x44, 0x07, 0x05, 0x02, 0x03, 0x0f, 0x08, 0x02, 0x02, 0x01, 0x03, + 0x02, 0x68, 0x0e, 0x09, 0x02, 0x01, 0x0c, 0x0a, 0x02, 0x00, 0x0b, 0x01, 0x00, 0x67, 0x06, 0x01, 0x04, 0x04, 0x6a, + 0x4d, 0x10, 0x0d, 0x02, 0x0b, 0x0b, 0x6b, 0x0b, 0x4e, 0x00, 0x00, 0x1f, 0x1e, 0x1d, 0x1c, 0x00, 0x1b, 0x00, 0x1b, + 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0d, + 0x1f, 0x2b, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x23, 0x37, 0x33, 0x37, 0x33, 0x07, 0x33, 0x37, 0x33, 0x07, 0x33, + 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x23, 0x37, 0x23, 0x07, 0x13, 0x33, 0x37, 0x23, 0x51, 0x37, 0x74, 0x09, + 0x87, 0x22, 0x7b, 0x09, 0x8d, 0x3a, 0x6a, 0x39, 0x61, 0x39, 0x69, 0x39, 0x75, 0x09, 0x88, 0x22, 0x7e, 0x09, 0x91, + 0x39, 0x6b, 0x39, 0x5f, 0x38, 0x54, 0x60, 0x22, 0x60, 0xc7, 0x65, 0x71, 0x66, 0xc7, 0xc7, 0xc7, 0xc7, 0x66, 0x71, + 0x65, 0xc7, 0xc7, 0xc7, 0x01, 0x2c, 0x71, 0x00, 0x03, 0x00, 0x19, 0xff, 0xc6, 0x02, 0x23, 0x02, 0xf8, 0x00, 0x24, + 0x00, 0x2a, 0x00, 0x31, 0x00, 0x70, 0x40, 0x17, 0x13, 0x01, 0x02, 0x03, 0x16, 0x01, 0x04, 0x02, 0x31, 0x2a, 0x1b, + 0x17, 0x08, 0x04, 0x06, 0x01, 0x04, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x20, + 0x00, 0x06, 0x00, 0x00, 0x06, 0x71, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, + 0x00, 0x69, 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x1b, 0x40, 0x1f, 0x00, 0x06, 0x00, + 0x06, 0x86, 0x00, 0x02, 0x04, 0x00, 0x02, 0x59, 0x00, 0x01, 0x05, 0x01, 0x00, 0x06, 0x01, 0x00, 0x69, 0x00, 0x04, + 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6c, 0x04, 0x4e, 0x59, 0x40, 0x0a, 0x11, 0x17, 0x17, 0x11, 0x18, 0x15, 0x10, + 0x07, 0x0d, 0x1d, 0x2b, 0x37, 0x26, 0x26, 0x27, 0x35, 0x16, 0x16, 0x17, 0x37, 0x2e, 0x02, 0x35, 0x34, 0x36, 0x36, + 0x37, 0x37, 0x33, 0x07, 0x16, 0x16, 0x17, 0x07, 0x26, 0x26, 0x27, 0x07, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x06, 0x06, 0x15, 0x14, 0x17, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x27, 0xc6, 0x33, 0x56, 0x24, 0x26, + 0x65, 0x3a, 0x23, 0x2b, 0x47, 0x2a, 0x3c, 0x69, 0x44, 0x11, 0x44, 0x10, 0x29, 0x44, 0x23, 0x34, 0x1c, 0x3d, 0x1d, + 0x1f, 0x2d, 0x48, 0x2a, 0x71, 0x80, 0x13, 0x44, 0x84, 0x19, 0x27, 0x27, 0x06, 0x1f, 0x26, 0x18, 0x11, 0x28, 0x03, + 0x14, 0x13, 0x82, 0x15, 0x22, 0x02, 0x9d, 0x11, 0x2e, 0x43, 0x30, 0x3c, 0x54, 0x30, 0x04, 0x4a, 0x4a, 0x05, 0x14, + 0x13, 0x71, 0x0e, 0x14, 0x02, 0x92, 0x11, 0x2c, 0x41, 0x33, 0x52, 0x70, 0x09, 0x61, 0x02, 0x6f, 0x03, 0x1e, 0x21, + 0x26, 0x10, 0xfe, 0xe0, 0x05, 0x23, 0x1e, 0x17, 0x1c, 0x07, 0x00, 0x00, 0x05, 0x00, 0x38, 0xff, 0xf7, 0x03, 0x34, + 0x02, 0xd4, 0x00, 0x0f, 0x00, 0x13, 0x00, 0x21, 0x00, 0x31, 0x00, 0x3f, 0x00, 0xd2, 0x4b, 0xb0, 0x19, 0x50, 0x58, + 0x40, 0x2c, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, + 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, + 0x06, 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x4b, 0xb0, 0x1a, 0x50, 0x58, 0x40, 0x30, 0x00, 0x07, 0x00, + 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x03, 0x61, 0x0d, 0x06, + 0x0b, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x34, 0x00, 0x07, 0x00, 0x09, 0x00, 0x07, 0x09, 0x6a, 0x0c, + 0x01, 0x04, 0x0a, 0x01, 0x00, 0x08, 0x04, 0x00, 0x69, 0x00, 0x02, 0x02, 0x6a, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x0b, 0x01, 0x03, 0x03, 0x6b, 0x4d, 0x0e, 0x01, 0x08, 0x08, 0x06, 0x61, 0x0d, 0x01, + 0x06, 0x06, 0x71, 0x06, 0x4e, 0x59, 0x59, 0x40, 0x2b, 0x33, 0x32, 0x23, 0x22, 0x15, 0x14, 0x10, 0x10, 0x01, 0x00, + 0x3a, 0x38, 0x32, 0x3f, 0x33, 0x3f, 0x2b, 0x29, 0x22, 0x31, 0x23, 0x31, 0x1c, 0x1a, 0x14, 0x21, 0x15, 0x21, 0x10, + 0x13, 0x10, 0x13, 0x12, 0x11, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x0f, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x03, 0x01, 0x33, 0x01, 0x03, 0x32, 0x3e, 0x02, 0x35, + 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x01, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc2, 0x43, 0x47, 0x15, 0x2f, + 0x4f, 0x3a, 0x43, 0x49, 0x15, 0x30, 0x4f, 0x8c, 0x02, 0x13, 0x73, 0xfd, 0xef, 0x1b, 0x12, 0x1d, 0x14, 0x0b, 0x1c, + 0x10, 0x1d, 0x14, 0x0c, 0x01, 0xb8, 0x46, 0x47, 0x16, 0x31, 0x4e, 0x38, 0x43, 0x49, 0x15, 0x30, 0x4e, 0x33, 0x12, + 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x14, 0x52, 0x4a, 0x2c, 0x65, 0x5a, 0x39, 0x4e, 0x4d, 0x2b, + 0x65, 0x5b, 0x3a, 0xfe, 0xec, 0x02, 0xca, 0xfd, 0x36, 0x01, 0x79, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, + 0x21, 0x2f, 0xfe, 0x7e, 0x4d, 0x46, 0x35, 0x6a, 0x58, 0x36, 0x4d, 0x4a, 0x2d, 0x67, 0x5b, 0x3a, 0x65, 0x27, 0x3c, + 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, 0x21, 0x2f, 0x00, 0x03, 0x00, 0x21, 0xff, 0xf6, 0x02, 0xba, 0x02, 0xd5, 0x00, + 0x20, 0x00, 0x2c, 0x00, 0x36, 0x00, 0x99, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x06, 0x01, 0x02, 0x04, 0x31, + 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x00, 0x05, 0x03, 0x4c, 0x1b, 0x40, 0x12, 0x06, 0x01, 0x02, + 0x04, 0x31, 0x30, 0x1b, 0x14, 0x13, 0x05, 0x05, 0x02, 0x1e, 0x01, 0x03, 0x05, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x24, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, + 0x5f, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x59, 0x40, 0x17, 0x2e, 0x2d, 0x01, 0x00, 0x2d, 0x36, 0x2e, 0x36, 0x28, 0x26, 0x1d, 0x1c, 0x18, 0x17, 0x0d, 0x0b, + 0x00, 0x20, 0x01, 0x20, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x35, 0x34, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x17, 0x36, 0x36, 0x37, 0x33, 0x06, 0x06, 0x07, 0x17, 0x23, + 0x27, 0x06, 0x06, 0x13, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x37, + 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xf4, 0x65, 0x6e, 0x54, 0x58, 0x25, 0x38, 0x60, 0x3c, 0x3f, 0x4e, 0x24, 0x5f, + 0x53, 0x5f, 0x1c, 0x22, 0x10, 0x92, 0x1e, 0x49, 0x30, 0x64, 0xab, 0x23, 0x27, 0x5f, 0x10, 0x28, 0x39, 0x1d, 0x14, + 0x22, 0x22, 0x0c, 0x31, 0x20, 0x36, 0x16, 0x6e, 0x23, 0x2a, 0x2a, 0x0a, 0x60, 0x59, 0x4b, 0x65, 0x2b, 0x3e, 0x40, + 0x44, 0x5b, 0x2e, 0x2a, 0x44, 0x28, 0x4a, 0x64, 0x22, 0x80, 0x23, 0x45, 0x28, 0x47, 0x7a, 0x32, 0x8c, 0x30, 0x1a, + 0x20, 0x01, 0xcb, 0x14, 0x33, 0x26, 0x1c, 0x19, 0x30, 0x21, 0x16, 0x2d, 0xfe, 0xa4, 0x11, 0x0c, 0xa0, 0x14, 0x33, + 0x2c, 0x1d, 0x2d, 0x00, 0x01, 0x00, 0x62, 0x01, 0xc8, 0x01, 0x0c, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, + 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, + 0x03, 0x0d, 0x17, 0x2b, 0x13, 0x13, 0x33, 0x03, 0x62, 0x23, 0x87, 0x4a, 0x01, 0xc8, 0x01, 0x02, 0xfe, 0xfe, 0x00, + 0x00, 0x01, 0x00, 0x24, 0xff, 0x62, 0x01, 0x9a, 0x02, 0xca, 0x00, 0x0e, 0x00, 0x19, 0x40, 0x16, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x16, 0x03, 0x0d, 0x17, + 0x2b, 0x17, 0x26, 0x26, 0x35, 0x34, 0x12, 0x37, 0x33, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x17, 0x6d, 0x25, 0x24, 0x7e, + 0x78, 0x80, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x9e, 0x41, 0x96, 0x50, 0xad, 0x01, 0x18, 0x7c, 0x4d, 0xb3, 0xcf, 0x77, + 0x4c, 0x94, 0x42, 0x00, 0x00, 0x01, 0xff, 0xba, 0xff, 0x62, 0x01, 0x30, 0x02, 0xd6, 0x00, 0x0e, 0x00, 0x2e, 0x4b, + 0xb0, 0x29, 0x50, 0x58, 0x40, 0x0c, 0x02, 0x01, 0x01, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x4e, 0x1b, + 0x40, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x85, 0x02, 0x01, 0x01, 0x01, 0x76, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x0e, 0x17, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x33, 0x16, 0x16, 0x15, 0x14, + 0x02, 0x07, 0x46, 0x47, 0x6e, 0x3f, 0x1e, 0x1b, 0x72, 0x25, 0x24, 0x7d, 0x78, 0x9e, 0x4e, 0xb2, 0xcf, 0x77, 0x4c, + 0xa0, 0x42, 0x41, 0xa2, 0x50, 0xae, 0xfe, 0xe8, 0x7b, 0x00, 0x01, 0x00, 0x55, 0x01, 0x19, 0x02, 0x35, 0x02, 0xfd, + 0x00, 0x0e, 0x00, 0x1d, 0x40, 0x1a, 0x09, 0x08, 0x07, 0x06, 0x04, 0x00, 0x4a, 0x0e, 0x0d, 0x0c, 0x05, 0x04, 0x03, + 0x02, 0x01, 0x08, 0x00, 0x49, 0x00, 0x00, 0x00, 0x76, 0x1a, 0x01, 0x0d, 0x17, 0x2b, 0x01, 0x27, 0x07, 0x27, 0x37, + 0x27, 0x37, 0x17, 0x37, 0x17, 0x07, 0x37, 0x07, 0x27, 0x17, 0x01, 0x5f, 0x2d, 0x61, 0x62, 0x86, 0xa0, 0x29, 0xa5, + 0x11, 0x7e, 0x3a, 0xbd, 0x08, 0xa6, 0x4e, 0x01, 0x19, 0xa6, 0x89, 0x4f, 0x7a, 0x2e, 0x71, 0x54, 0xb3, 0x18, 0xac, + 0x0d, 0x79, 0x15, 0xa5, 0x00, 0x01, 0x00, 0x35, 0x00, 0x6f, 0x02, 0x1a, 0x02, 0x54, 0x00, 0x0b, 0x00, 0x26, 0x40, + 0x23, 0x00, 0x05, 0x00, 0x02, 0x05, 0x57, 0x04, 0x01, 0x00, 0x03, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x05, + 0x05, 0x02, 0x5f, 0x00, 0x02, 0x05, 0x02, 0x4f, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x06, 0x0d, 0x1c, 0x2b, 0x01, + 0x33, 0x15, 0x23, 0x15, 0x23, 0x35, 0x23, 0x35, 0x33, 0x35, 0x33, 0x01, 0x5d, 0xbd, 0xbd, 0x6b, 0xbd, 0xbd, 0x6b, + 0x01, 0x96, 0x6b, 0xbc, 0xbc, 0x6b, 0xbe, 0x00, 0x00, 0x01, 0xff, 0xd0, 0xff, 0x7f, 0x00, 0xc0, 0x00, 0x74, 0x00, + 0x08, 0x00, 0x1e, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x13, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x33, + 0x17, 0x06, 0x06, 0x07, 0x30, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, 0x24, 0x81, 0x3b, 0x86, 0x34, 0x0b, 0x35, + 0x7e, 0x37, 0x00, 0x01, 0x00, 0x11, 0x00, 0xce, 0x01, 0x2c, 0x01, 0x4a, 0x00, 0x03, 0x00, 0x1e, 0x40, 0x1b, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x37, 0x37, 0x21, 0x07, 0x11, 0x1a, 0x01, 0x01, 0x1a, 0xce, 0x7c, + 0x7c, 0x00, 0x01, 0x00, 0x08, 0xff, 0xf3, 0x00, 0xb7, 0x00, 0x9b, 0x00, 0x0b, 0x00, 0x1a, 0x40, 0x17, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x02, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x03, + 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x50, 0x21, 0x27, 0x3a, + 0x2c, 0x21, 0x28, 0x37, 0x0d, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, 0x01, 0xff, 0xd3, 0xff, + 0xfa, 0x01, 0xf1, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x07, 0x01, 0x33, 0x01, + 0x2d, 0x01, 0x95, 0x89, 0xfe, 0x6c, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x02, 0x00, 0x20, 0xff, 0xf6, 0x02, 0x1e, + 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x21, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, + 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, 0x01, 0x00, 0x1a, + 0x18, 0x10, 0x21, 0x11, 0x21, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x03, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x03, 0x15, 0x14, 0x16, 0xe5, 0x65, 0x60, 0x28, 0x50, 0x76, 0x4d, 0x5c, 0x67, 0x24, 0x4b, 0x77, 0x47, 0x1c, + 0x30, 0x26, 0x19, 0x0e, 0x1e, 0x1e, 0x1e, 0x31, 0x25, 0x19, 0x0d, 0x1b, 0x0a, 0x7c, 0x72, 0x62, 0xb3, 0x8b, 0x51, + 0x6e, 0x79, 0x5f, 0xb4, 0x90, 0x55, 0x7a, 0x31, 0x53, 0x65, 0x6b, 0x2f, 0x36, 0x32, 0x36, 0x57, 0x65, 0x63, 0x25, + 0x37, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x59, 0x00, 0x00, 0x01, 0xe7, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x1b, 0x40, 0x18, + 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x01, 0x4e, + 0x11, 0x19, 0x02, 0x0d, 0x18, 0x2b, 0x01, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0x07, 0x27, 0x25, 0x33, 0x03, 0x23, + 0x01, 0x13, 0x05, 0x16, 0x0a, 0x09, 0x26, 0x10, 0x5f, 0x41, 0x01, 0x14, 0x7a, 0x97, 0x95, 0x01, 0x95, 0x1a, 0x52, + 0x20, 0x07, 0x1d, 0x0a, 0x3c, 0x69, 0xaa, 0xfd, 0x36, 0x00, 0x01, 0xff, 0xe8, 0x00, 0x00, 0x02, 0x18, 0x02, 0xd4, + 0x00, 0x1c, 0x00, 0x2f, 0x40, 0x2c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x00, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x28, 0x25, 0x28, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x37, 0x3e, 0x02, 0x35, + 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x07, + 0x15, 0x21, 0x07, 0x18, 0x15, 0xe9, 0x3a, 0x44, 0x1d, 0x28, 0x22, 0x24, 0x44, 0x2e, 0x47, 0x32, 0x77, 0x4c, 0x46, + 0x59, 0x2a, 0x37, 0x5e, 0x3d, 0x83, 0x01, 0x15, 0x1a, 0x68, 0xcf, 0x34, 0x4a, 0x3b, 0x1b, 0x25, 0x26, 0x24, 0x26, + 0x63, 0x2b, 0x3a, 0x32, 0x4f, 0x2d, 0x3f, 0x68, 0x5d, 0x32, 0x6c, 0x05, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x07, 0xff, + 0xf6, 0x02, 0x1b, 0x02, 0xd4, 0x00, 0x2b, 0x00, 0x4a, 0x40, 0x47, 0x1b, 0x01, 0x04, 0x05, 0x1a, 0x01, 0x03, 0x04, + 0x24, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x03, 0x00, 0x02, 0x01, + 0x03, 0x02, 0x69, 0x00, 0x04, 0x04, 0x05, 0x61, 0x00, 0x05, 0x05, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1f, 0x1d, 0x18, 0x16, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, + 0x2b, 0x01, 0x2b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc4, 0x37, 0x62, 0x24, 0x29, 0x60, + 0x2d, 0x47, 0x59, 0x35, 0x49, 0x43, 0x16, 0x24, 0x2b, 0x50, 0x34, 0x26, 0x2a, 0x2c, 0x46, 0x1a, 0x3e, 0x30, 0x6b, + 0x4f, 0x63, 0x63, 0x5a, 0x54, 0x36, 0x4c, 0x3e, 0x84, 0x0a, 0x14, 0x13, 0x82, 0x18, 0x19, 0x3a, 0x3b, 0x24, 0x30, + 0x6c, 0x16, 0x32, 0x2a, 0x1d, 0x28, 0x20, 0x11, 0x64, 0x20, 0x27, 0x5d, 0x46, 0x4a, 0x67, 0x0f, 0x04, 0x0a, 0x48, + 0x44, 0x38, 0x68, 0x41, 0x00, 0x00, 0x02, 0xff, 0xf4, 0x00, 0x00, 0x02, 0x1b, 0x02, 0xca, 0x00, 0x0a, 0x00, 0x15, + 0x00, 0x2e, 0x40, 0x2b, 0x11, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x05, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x02, 0x00, + 0x68, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x0a, + 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0d, 0x1a, 0x2b, 0x33, 0x37, 0x21, 0x37, 0x01, 0x33, 0x03, 0x33, 0x07, + 0x23, 0x07, 0x03, 0x33, 0x37, 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x07, 0xf5, 0x1f, 0xfe, 0xe0, 0x17, 0x01, 0x78, + 0x98, 0x5f, 0x53, 0x19, 0x53, 0x1f, 0xef, 0x98, 0x1c, 0x06, 0x0f, 0x0f, 0x04, 0x05, 0x0b, 0x22, 0x11, 0x94, 0x72, + 0x01, 0xc4, 0xfe, 0x3f, 0x75, 0x94, 0x01, 0x09, 0x79, 0x1a, 0x3c, 0x33, 0x0c, 0x13, 0x30, 0x15, 0x00, 0x00, 0x01, + 0x00, 0x0d, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xca, 0x00, 0x21, 0x00, 0x44, 0x40, 0x41, 0x17, 0x12, 0x02, 0x02, 0x05, + 0x11, 0x04, 0x02, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x05, 0x00, 0x02, 0x01, 0x05, 0x02, 0x69, + 0x00, 0x04, 0x04, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, + 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1b, 0x19, 0x16, 0x15, 0x14, 0x13, 0x0f, 0x0d, 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, + 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, + 0x22, 0x06, 0x07, 0x27, 0x13, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0xc7, 0x3a, 0x61, 0x1f, 0x24, 0x58, 0x30, 0x3c, 0x46, 0x1e, 0x2f, 0x3e, 0x1e, 0x38, 0x12, 0x33, 0x65, 0x01, 0x71, + 0x1b, 0xef, 0x2b, 0x0c, 0x1f, 0x13, 0x36, 0x58, 0x33, 0x3f, 0x83, 0x0a, 0x17, 0x11, 0x83, 0x14, 0x1c, 0x27, 0x3b, + 0x1f, 0x26, 0x36, 0x0b, 0x05, 0x26, 0x01, 0x66, 0x80, 0x8f, 0x02, 0x05, 0x29, 0x54, 0x41, 0x4a, 0x7b, 0x49, 0x00, + 0x02, 0x00, 0x2b, 0xff, 0xf6, 0x02, 0x33, 0x02, 0xd5, 0x00, 0x1f, 0x00, 0x30, 0x00, 0x47, 0x40, 0x44, 0x0d, 0x01, + 0x02, 0x01, 0x0e, 0x01, 0x03, 0x02, 0x14, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, + 0x69, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x21, 0x20, 0x01, 0x00, 0x28, 0x26, 0x20, 0x30, 0x21, 0x30, 0x19, 0x17, 0x12, 0x10, + 0x0b, 0x09, 0x00, 0x1f, 0x01, 0x1f, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, 0x37, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x06, 0x06, 0x15, 0x14, + 0x16, 0xfc, 0x67, 0x6a, 0x26, 0x47, 0x31, 0x31, 0x7a, 0x52, 0x1f, 0x3b, 0x13, 0x19, 0x12, 0x33, 0x18, 0x64, 0x74, + 0x1e, 0x04, 0x19, 0x4a, 0x35, 0x4a, 0x56, 0x19, 0x3c, 0x65, 0x46, 0x25, 0x30, 0x18, 0x21, 0x21, 0x1c, 0x30, 0x1f, + 0x04, 0x02, 0x02, 0x26, 0x0a, 0x7c, 0x73, 0x4e, 0x99, 0x84, 0x2d, 0x2c, 0x2c, 0x08, 0x05, 0x78, 0x05, 0x07, 0x6f, + 0x6e, 0x23, 0x2e, 0x5c, 0x59, 0x2a, 0x65, 0x5b, 0x3b, 0x79, 0x30, 0x4a, 0x27, 0x23, 0x29, 0x1e, 0x2c, 0x17, 0x0b, + 0x17, 0x0b, 0x29, 0x36, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x02, 0x52, 0x02, 0xca, 0x00, 0x06, 0x00, 0x1f, 0x40, + 0x1c, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x26, + 0x01, 0x68, 0xfe, 0xcd, 0x1b, 0x01, 0xdc, 0x14, 0xfe, 0x91, 0x02, 0x4b, 0x7f, 0x5f, 0xfd, 0x95, 0x00, 0x00, 0x03, + 0x00, 0x1b, 0xff, 0xf6, 0x02, 0x26, 0x02, 0xd5, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x34, 0x00, 0x35, 0x40, 0x32, 0x2f, + 0x15, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, + 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x2a, 0x29, 0x01, 0x00, 0x29, 0x34, 0x2a, 0x34, + 0x24, 0x22, 0x0e, 0x0c, 0x00, 0x1c, 0x01, 0x1c, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x1e, 0x02, 0x15, 0x14, + 0x06, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x03, 0x32, 0x36, 0x35, 0x34, + 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xfb, 0x70, 0x70, 0x58, 0x52, 0x1e, 0x33, 0x36, 0x69, 0x4d, 0x43, 0x57, + 0x2c, 0x2b, 0x45, 0x28, 0x1a, 0x31, 0x1f, 0x36, 0x70, 0x14, 0x2a, 0x30, 0x26, 0x1f, 0x27, 0x2a, 0x21, 0x1d, 0x33, + 0x30, 0x2b, 0x22, 0x38, 0x38, 0x31, 0x0a, 0x68, 0x4d, 0x4d, 0x65, 0x1e, 0x17, 0x49, 0x32, 0x37, 0x5b, 0x36, 0x2d, + 0x4a, 0x2c, 0x34, 0x49, 0x31, 0x0e, 0x11, 0x30, 0x43, 0x2e, 0x34, 0x5f, 0x3b, 0x01, 0xbe, 0x11, 0x34, 0x27, 0x21, + 0x26, 0x2f, 0x22, 0x23, 0x30, 0xfe, 0xa2, 0x3a, 0x24, 0x29, 0x38, 0x16, 0x16, 0x3d, 0x2c, 0x27, 0x2f, 0x00, 0x00, + 0x02, 0x00, 0x2a, 0xff, 0xf6, 0x02, 0x15, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x32, 0x00, 0x47, 0x40, 0x44, 0x0c, 0x01, + 0x02, 0x04, 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x01, 0x04, + 0x02, 0x69, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x23, 0x22, 0x01, 0x00, 0x2d, 0x2b, 0x22, 0x32, 0x23, 0x32, 0x19, 0x17, 0x11, 0x0f, + 0x08, 0x06, 0x00, 0x21, 0x01, 0x21, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, + 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x06, 0x07, 0x06, 0x06, 0x13, 0x32, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0x9f, 0x21, 0x40, 0x14, 0x13, 0x3b, 0x21, 0x36, 0x4c, 0x32, 0x20, 0x0a, 0x04, 0x18, 0x46, 0x32, 0x55, + 0x52, 0x19, 0x3c, 0x6a, 0x50, 0x5c, 0x6e, 0x1e, 0x3c, 0x2e, 0x2a, 0x74, 0x26, 0x1d, 0x2c, 0x1c, 0x04, 0x02, 0x02, + 0x22, 0x25, 0x24, 0x30, 0x18, 0x25, 0x0a, 0x0a, 0x06, 0x7d, 0x07, 0x0d, 0x25, 0x3e, 0x4e, 0x28, 0x22, 0x2b, 0x6c, + 0x52, 0x28, 0x61, 0x59, 0x3a, 0x6f, 0x7d, 0x46, 0x98, 0x88, 0x30, 0x2b, 0x32, 0x01, 0x79, 0x1f, 0x2e, 0x16, 0x0b, + 0x17, 0x0b, 0x29, 0x34, 0x2f, 0x45, 0x23, 0x2a, 0x2c, 0x00, 0x00, 0x02, 0x00, 0x08, 0xff, 0xf3, 0x01, 0x10, 0x02, + 0x2c, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x05, 0x01, 0x02, 0x02, 0x71, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, 0x13, 0x11, + 0x0c, 0x17, 0x0d, 0x17, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x03, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0x89, 0x21, 0x27, 0x3a, 0x2c, 0x21, 0x28, 0x37, 0x01, 0x85, 0x21, + 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfe, 0x6e, 0x21, 0x21, 0x31, 0x35, 0x21, 0x22, 0x34, 0x31, 0x00, 0x00, + 0x02, 0xff, 0xca, 0xff, 0x7f, 0x01, 0x10, 0x02, 0x2c, 0x00, 0x0b, 0x00, 0x14, 0x00, 0x2a, 0x40, 0x27, 0x00, 0x02, + 0x05, 0x01, 0x03, 0x02, 0x03, 0x63, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x00, 0x4e, 0x0c, + 0x0c, 0x01, 0x00, 0x0c, 0x14, 0x0c, 0x14, 0x10, 0x0f, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, + 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x36, 0x36, 0x37, 0x33, 0x17, 0x06, + 0x06, 0x07, 0xa9, 0x21, 0x27, 0x39, 0x2d, 0x20, 0x29, 0x37, 0xfe, 0xf1, 0x1a, 0x32, 0x13, 0x8d, 0x04, 0x18, 0x44, + 0x24, 0x01, 0x85, 0x21, 0x20, 0x32, 0x34, 0x20, 0x22, 0x34, 0x31, 0xfd, 0xfa, 0x3b, 0x86, 0x34, 0x0b, 0x35, 0x7e, + 0x37, 0x00, 0x01, 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x03, 0x00, 0x01, + 0x32, 0x2b, 0x25, 0x25, 0x35, 0x25, 0x15, 0x05, 0x05, 0x02, 0x1a, 0xfe, 0x1b, 0x01, 0xe5, 0xfe, 0xb2, 0x01, 0x4e, + 0x63, 0xd6, 0x46, 0xf2, 0x75, 0x9b, 0x89, 0x00, 0x02, 0x00, 0x35, 0x00, 0xcc, 0x02, 0x1a, 0x01, 0xf4, 0x00, 0x03, + 0x00, 0x07, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x00, 0x04, 0x01, 0x01, 0x02, 0x00, 0x01, 0x67, 0x00, 0x02, 0x03, 0x03, + 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x05, 0x01, 0x03, 0x02, 0x03, 0x4f, 0x04, 0x04, 0x00, 0x00, 0x04, 0x07, + 0x04, 0x07, 0x06, 0x05, 0x00, 0x03, 0x00, 0x03, 0x11, 0x06, 0x0d, 0x17, 0x2b, 0x13, 0x35, 0x21, 0x15, 0x05, 0x35, + 0x21, 0x15, 0x35, 0x01, 0xe5, 0xfe, 0x1b, 0x01, 0xe5, 0x01, 0x8a, 0x6a, 0x6a, 0xbe, 0x6b, 0x6b, 0x00, 0x00, 0x01, + 0x00, 0x35, 0x00, 0x63, 0x02, 0x1a, 0x02, 0x71, 0x00, 0x06, 0x00, 0x06, 0xb3, 0x06, 0x03, 0x01, 0x32, 0x2b, 0x37, + 0x25, 0x25, 0x35, 0x05, 0x15, 0x05, 0x35, 0x01, 0x4e, 0xfe, 0xb2, 0x01, 0xe5, 0xfe, 0x1b, 0xd8, 0x89, 0x9b, 0x75, + 0xf2, 0x46, 0xd6, 0x00, 0x00, 0x02, 0x00, 0x4d, 0xff, 0xf3, 0x01, 0xeb, 0x02, 0xd4, 0x00, 0x1b, 0x00, 0x27, 0x00, + 0x3f, 0x40, 0x3c, 0x0d, 0x01, 0x00, 0x01, 0x0c, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, + 0x02, 0x04, 0x80, 0x00, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x04, 0x04, 0x03, 0x61, 0x06, + 0x01, 0x03, 0x03, 0x71, 0x03, 0x4e, 0x1d, 0x1c, 0x00, 0x00, 0x23, 0x21, 0x1c, 0x27, 0x1d, 0x27, 0x00, 0x1b, 0x00, + 0x1b, 0x25, 0x28, 0x07, 0x0d, 0x18, 0x2b, 0x37, 0x36, 0x36, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, + 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x0e, 0x02, 0x07, 0x07, 0x22, 0x26, 0x35, + 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x7f, 0x0d, 0x36, 0x3c, 0x31, 0x2c, 0x1e, 0x23, 0x23, 0x47, 0x2c, + 0x2d, 0x2d, 0x6d, 0x3f, 0x58, 0x63, 0x26, 0x43, 0x2a, 0x1d, 0x23, 0x14, 0x07, 0x64, 0x2a, 0x22, 0x2d, 0x37, 0x21, + 0x28, 0x35, 0xed, 0x45, 0x5b, 0x28, 0x21, 0x2d, 0x1f, 0x1b, 0x1f, 0x1c, 0x15, 0x6c, 0x19, 0x24, 0x56, 0x4c, 0x32, + 0x47, 0x38, 0x1c, 0x13, 0x21, 0x27, 0x1d, 0xfa, 0x2b, 0x1a, 0x24, 0x3d, 0x25, 0x22, 0x29, 0x36, 0x00, 0x00, 0x02, + 0x00, 0x2d, 0xff, 0xa5, 0x03, 0x4e, 0x02, 0xca, 0x00, 0x40, 0x00, 0x4f, 0x00, 0x93, 0x40, 0x16, 0x23, 0x01, 0x09, + 0x04, 0x45, 0x01, 0x05, 0x09, 0x14, 0x01, 0x02, 0x05, 0x3d, 0x01, 0x07, 0x02, 0x3e, 0x01, 0x00, 0x07, 0x05, 0x4c, + 0x4b, 0xb0, 0x15, 0x50, 0x58, 0x40, 0x28, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, + 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x09, + 0x09, 0x04, 0x61, 0x00, 0x04, 0x04, 0x6d, 0x09, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x00, 0x09, 0x05, 0x04, 0x09, + 0x69, 0x0b, 0x08, 0x02, 0x05, 0x03, 0x01, 0x02, 0x07, 0x05, 0x02, 0x69, 0x00, 0x07, 0x0a, 0x01, 0x00, 0x07, 0x00, + 0x65, 0x00, 0x06, 0x06, 0x01, 0x61, 0x00, 0x01, 0x01, 0x6a, 0x06, 0x4e, 0x59, 0x40, 0x1f, 0x42, 0x41, 0x01, 0x00, + 0x49, 0x47, 0x41, 0x4f, 0x42, 0x4f, 0x3b, 0x39, 0x33, 0x31, 0x2b, 0x29, 0x21, 0x1f, 0x19, 0x17, 0x12, 0x10, 0x0a, + 0x08, 0x00, 0x40, 0x01, 0x40, 0x0c, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, + 0x16, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x06, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x06, 0x15, 0x14, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0x03, 0x32, 0x36, 0x37, 0x37, 0x26, + 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x87, 0x72, 0x9a, 0x4e, 0x4c, 0x83, 0xa9, 0x5d, 0x9b, 0xb1, + 0x20, 0x3f, 0x5a, 0x39, 0x27, 0x3a, 0x09, 0x05, 0x15, 0x39, 0x2f, 0x37, 0x4c, 0x23, 0x42, 0x5f, 0x3b, 0x36, 0x4c, + 0x1e, 0x34, 0x05, 0x08, 0x10, 0x0c, 0x1b, 0x2d, 0x21, 0x12, 0x73, 0x79, 0x63, 0x9d, 0x5c, 0x32, 0x6e, 0x59, 0x3e, + 0x65, 0x34, 0x2f, 0x71, 0x40, 0x27, 0x31, 0x10, 0x1c, 0x09, 0x12, 0x0d, 0x23, 0x34, 0x22, 0x11, 0x1c, 0x5b, 0x59, + 0x98, 0x5e, 0x72, 0xaf, 0x78, 0x3d, 0xa0, 0x90, 0x3b, 0x6f, 0x58, 0x34, 0x23, 0x25, 0x21, 0x27, 0x47, 0x50, 0x33, + 0x61, 0x4e, 0x2e, 0x10, 0x0b, 0xcd, 0x16, 0x1f, 0x10, 0x12, 0x0f, 0x27, 0x40, 0x4d, 0x27, 0x63, 0x73, 0x5a, 0xa5, + 0x70, 0x44, 0x74, 0x45, 0x16, 0x14, 0x5b, 0x13, 0x19, 0x01, 0x18, 0x49, 0x3b, 0x6c, 0x02, 0x03, 0x23, 0x37, 0x3d, + 0x1a, 0x26, 0x1e, 0x00, 0x02, 0xff, 0xc4, 0x00, 0x00, 0x02, 0x38, 0x02, 0xca, 0x00, 0x07, 0x00, 0x11, 0x00, 0x2c, + 0x40, 0x29, 0x0d, 0x01, 0x04, 0x00, 0x01, 0x4c, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x02, 0x68, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x05, 0x03, 0x02, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x09, 0x08, 0x00, 0x07, 0x00, 0x07, 0x11, + 0x11, 0x11, 0x06, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, 0x13, 0x33, 0x27, 0x26, 0x26, + 0x37, 0x23, 0x06, 0x06, 0x07, 0x3c, 0x01, 0x76, 0xb6, 0x48, 0x91, 0x0c, 0xe7, 0x54, 0x91, 0xa3, 0x0d, 0x02, 0x04, + 0x01, 0x02, 0x0a, 0x18, 0x0f, 0x02, 0xca, 0xfd, 0x36, 0xaa, 0xaa, 0x01, 0x29, 0xb8, 0x1d, 0x3c, 0x1f, 0x1b, 0x35, + 0x1f, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x63, 0x02, 0xca, 0x00, 0x10, 0x00, 0x18, 0x00, 0x21, 0x00, 0x43, + 0x40, 0x40, 0x08, 0x01, 0x05, 0x02, 0x01, 0x4c, 0x07, 0x01, 0x02, 0x00, 0x05, 0x04, 0x02, 0x05, 0x67, 0x00, 0x03, + 0x03, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x08, 0x01, 0x04, 0x04, 0x01, 0x5f, 0x06, 0x01, 0x01, 0x01, 0x6b, + 0x01, 0x4e, 0x1a, 0x19, 0x12, 0x11, 0x00, 0x00, 0x20, 0x1e, 0x19, 0x21, 0x1a, 0x21, 0x17, 0x15, 0x11, 0x18, 0x12, + 0x18, 0x00, 0x10, 0x00, 0x0f, 0x21, 0x09, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, + 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, + 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xd0, 0x66, 0x7c, 0x52, 0x4a, 0x31, 0x3a, 0x4a, 0x7f, 0x50, 0x3a, + 0x35, 0x41, 0x53, 0x4a, 0x22, 0x17, 0x37, 0x43, 0x2c, 0x2d, 0x51, 0x28, 0x02, 0xca, 0x49, 0x56, 0x49, 0x5e, 0x10, + 0x04, 0x0d, 0x45, 0x35, 0x51, 0x67, 0x31, 0x01, 0xaf, 0x2b, 0x31, 0x43, 0x9f, 0xfe, 0xce, 0x37, 0x34, 0x26, 0x29, + 0xba, 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0x8c, 0x02, 0xd5, 0x00, 0x1d, 0x00, 0x37, 0x40, 0x34, 0x0c, + 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, 0x02, 0x01, 0x61, + 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, + 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1d, 0x01, 0x1d, 0x05, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, + 0x3e, 0x03, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x15, 0x06, 0x01, 0x3f, 0x80, 0x84, 0x1d, 0x3b, 0x5a, 0x7c, 0x50, 0x3f, 0x67, 0x2d, 0x3a, 0x26, 0x49, 0x2a, + 0x38, 0x55, 0x39, 0x1d, 0x46, 0x3f, 0x2b, 0x51, 0x2f, 0x5c, 0x0a, 0x97, 0x7d, 0x40, 0x83, 0x76, 0x5c, 0x36, 0x1d, + 0x1a, 0x78, 0x16, 0x19, 0x38, 0x5d, 0x73, 0x3c, 0x4b, 0x51, 0x14, 0x12, 0x7e, 0x27, 0x00, 0x00, 0x02, 0x00, 0x1a, + 0x00, 0x00, 0x02, 0x86, 0x02, 0xca, 0x00, 0x09, 0x00, 0x13, 0x00, 0x2c, 0x40, 0x29, 0x00, 0x03, 0x03, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x01, 0x5f, 0x04, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x0b, + 0x0a, 0x00, 0x00, 0x12, 0x10, 0x0a, 0x13, 0x0b, 0x13, 0x00, 0x09, 0x00, 0x08, 0x21, 0x06, 0x0d, 0x17, 0x2b, 0x33, + 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x37, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x03, + 0x1a, 0x97, 0xbd, 0x83, 0x95, 0x61, 0xb8, 0x82, 0x13, 0x4a, 0x6b, 0x39, 0x49, 0x3f, 0x36, 0x62, 0x02, 0xca, 0x8b, + 0x89, 0x85, 0xc5, 0x6c, 0x7e, 0x4f, 0x8a, 0x59, 0x50, 0x4d, 0xfe, 0x31, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, + 0x02, 0x41, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x2f, 0x40, 0x2c, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, + 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x04, 0x04, 0x05, 0x5f, 0x06, 0x01, 0x05, 0x05, 0x6b, + 0x05, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, + 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, 0x07, 0x33, 0x07, 0x1a, 0x97, 0x01, 0x90, 0x1b, 0xf8, 0x21, 0xe8, 0x1b, + 0xe8, 0x27, 0xf9, 0x1a, 0x02, 0xca, 0x7d, 0x9c, 0x7d, 0xb5, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, + 0x3f, 0x02, 0xca, 0x00, 0x09, 0x00, 0x29, 0x40, 0x26, 0x00, 0x02, 0x00, 0x03, 0x04, 0x02, 0x03, 0x67, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x01, 0x04, 0x04, 0x6b, 0x04, 0x4e, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x09, 0x11, 0x11, 0x11, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x21, 0x07, 0x23, 0x07, 0x33, 0x07, 0x23, + 0x03, 0x1a, 0x97, 0x01, 0x8e, 0x1b, 0xf7, 0x26, 0xe6, 0x1b, 0xe7, 0x3a, 0x02, 0xca, 0x7d, 0xb6, 0x7e, 0xfe, 0xe7, + 0x00, 0x00, 0x01, 0x00, 0x3b, 0xff, 0xf6, 0x02, 0xa7, 0x02, 0xd5, 0x00, 0x21, 0x00, 0x3e, 0x40, 0x3b, 0x0b, 0x01, + 0x02, 0x01, 0x0c, 0x01, 0x05, 0x02, 0x02, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x67, 0x00, 0x02, 0x02, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x01, 0x00, 0x1e, 0x1d, 0x1c, 0x1b, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x21, 0x01, 0x21, 0x07, 0x0d, 0x16, + 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, + 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x23, 0x37, 0x21, 0x03, 0x06, 0x06, 0x01, 0x48, 0x7b, 0x92, 0x35, + 0x67, 0x97, 0x62, 0x40, 0x6b, 0x2c, 0x3a, 0x21, 0x4f, 0x2e, 0x3f, 0x5d, 0x3e, 0x1f, 0x43, 0x43, 0x1b, 0x29, 0x14, + 0x21, 0x7b, 0x1b, 0x01, 0x0f, 0x50, 0x30, 0x72, 0x0a, 0x8f, 0x88, 0x5a, 0xa4, 0x80, 0x4a, 0x19, 0x17, 0x7b, 0x11, + 0x1a, 0x39, 0x5e, 0x73, 0x3a, 0x4a, 0x51, 0x06, 0x05, 0x97, 0x7a, 0xfe, 0x8b, 0x10, 0x17, 0x00, 0x01, 0x00, 0x1a, + 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0b, 0x00, 0x27, 0x40, 0x24, 0x00, 0x01, 0x00, 0x04, 0x03, 0x01, 0x04, + 0x68, 0x02, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x05, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x0b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x07, 0x0d, 0x1b, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x13, 0x33, 0x03, + 0x23, 0x13, 0x23, 0x03, 0x1a, 0x97, 0x97, 0x3a, 0xe2, 0x3b, 0x96, 0x97, 0x96, 0x40, 0xe2, 0x41, 0x02, 0xca, 0xfe, + 0xe9, 0x01, 0x17, 0xfd, 0x36, 0x01, 0x33, 0xfe, 0xcd, 0x00, 0x00, 0x01, 0xff, 0xe3, 0x00, 0x00, 0x01, 0xb6, 0x02, + 0xca, 0x00, 0x0b, 0x00, 0x22, 0x40, 0x1f, 0x0a, 0x09, 0x04, 0x03, 0x04, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x00, + 0x6a, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x15, 0x03, 0x0d, 0x17, + 0x2b, 0x23, 0x37, 0x37, 0x13, 0x27, 0x37, 0x21, 0x07, 0x07, 0x03, 0x17, 0x07, 0x1d, 0x12, 0x5b, 0x62, 0x4a, 0x12, + 0x01, 0x3c, 0x12, 0x5d, 0x62, 0x4c, 0x12, 0x56, 0x28, 0x01, 0xce, 0x28, 0x56, 0x56, 0x28, 0xfe, 0x32, 0x28, 0x56, + 0x00, 0x00, 0x01, 0xff, 0x62, 0xff, 0x2d, 0x01, 0x54, 0x02, 0xca, 0x00, 0x0f, 0x00, 0x28, 0x40, 0x25, 0x04, 0x01, + 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x01, 0x03, 0x01, 0x00, 0x01, 0x00, 0x65, 0x00, 0x02, 0x02, + 0x6a, 0x02, 0x4e, 0x01, 0x00, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x0f, 0x01, 0x0f, 0x04, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x37, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x06, 0x41, 0x19, 0x32, 0x12, 0x01, + 0x11, 0x26, 0x18, 0x2d, 0x3e, 0x0f, 0x91, 0x97, 0x94, 0x1b, 0x78, 0xd3, 0x07, 0x06, 0x7d, 0x04, 0x07, 0x34, 0x46, + 0x02, 0xa4, 0xfd, 0x4a, 0x7e, 0x69, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x02, 0xc1, 0x02, 0xca, 0x00, 0x0c, 0x00, + 0x25, 0x40, 0x22, 0x0a, 0x07, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, + 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x12, 0x13, 0x11, 0x05, 0x0d, 0x19, 0x2b, + 0x33, 0x13, 0x33, 0x03, 0x37, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x07, 0x07, 0x1a, 0x97, 0x95, 0x4b, 0x4c, 0xca, + 0xb0, 0xfe, 0xde, 0x8e, 0xa5, 0x67, 0x3d, 0x35, 0x02, 0xca, 0xfe, 0xa7, 0x66, 0xf3, 0xfe, 0xaa, 0xfe, 0x8c, 0x01, + 0x21, 0x22, 0xff, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x01, 0xc3, 0x02, 0xca, 0x00, 0x05, 0x00, 0x1f, 0x40, 0x1c, + 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x00, 0x01, 0x01, 0x02, 0x60, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x05, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x33, 0x07, 0x1a, 0x97, 0x95, + 0x7d, 0xfa, 0x1a, 0x02, 0xca, 0xfd, 0xb3, 0x7d, 0x00, 0x01, 0x00, 0x1a, 0x00, 0x00, 0x03, 0x75, 0x02, 0xca, 0x00, + 0x17, 0x00, 0x27, 0x40, 0x24, 0x11, 0x0d, 0x03, 0x03, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x17, 0x17, 0x11, 0x13, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x01, 0x33, 0x03, 0x23, 0x13, 0x3e, 0x02, 0x37, 0x23, 0x01, + 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x1a, 0x97, 0xc5, 0x20, 0x04, 0x01, 0x0c, 0xcf, 0x97, 0x89, 0x47, 0x07, + 0x13, 0x13, 0x08, 0x04, 0xfe, 0xea, 0x89, 0x1e, 0x04, 0x02, 0x0c, 0x0f, 0x09, 0x46, 0x02, 0xca, 0xfd, 0xea, 0x02, + 0x16, 0xfd, 0x36, 0x01, 0x52, 0x22, 0x4d, 0x4b, 0x1d, 0xfd, 0xd7, 0x02, 0x29, 0x15, 0x49, 0x56, 0x29, 0xfe, 0xb4, + 0x00, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x02, 0xfb, 0x02, 0xca, 0x00, 0x13, 0x00, 0x24, 0x40, 0x21, 0x0d, 0x03, + 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x13, 0x11, 0x17, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x13, 0x33, 0x3e, + 0x02, 0x37, 0x13, 0x33, 0x03, 0x23, 0x03, 0x23, 0x0e, 0x02, 0x07, 0x03, 0x19, 0x97, 0xad, 0xab, 0x03, 0x03, 0x0a, + 0x0c, 0x06, 0x48, 0x89, 0x97, 0xad, 0xac, 0x04, 0x01, 0x09, 0x0d, 0x08, 0x46, 0x02, 0xca, 0xfd, 0xf5, 0x17, 0x42, + 0x46, 0x1c, 0x01, 0x50, 0xfd, 0x36, 0x02, 0x19, 0x10, 0x47, 0x53, 0x22, 0xfe, 0xb3, 0x00, 0x02, 0x00, 0x3b, 0xff, + 0xf6, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x0f, 0x00, 0x1f, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, + 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x11, 0x10, + 0x01, 0x00, 0x19, 0x17, 0x10, 0x1f, 0x11, 0x1f, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x0f, 0x06, 0x0d, 0x16, 0x2b, 0x05, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, + 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x4a, 0x86, 0x89, 0x30, 0x5e, 0x8e, 0x5d, 0x80, 0x88, 0x2d, + 0x5c, 0x8b, 0x53, 0x2d, 0x4b, 0x36, 0x1e, 0x40, 0x39, 0x30, 0x4d, 0x38, 0x1d, 0x42, 0x0a, 0x96, 0x7e, 0x57, 0xa4, + 0x83, 0x4d, 0x96, 0x7f, 0x57, 0xa4, 0x82, 0x4d, 0x7f, 0x34, 0x5c, 0x77, 0x43, 0x47, 0x50, 0x37, 0x5e, 0x76, 0x40, + 0x48, 0x4e, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x67, 0x02, 0xca, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x30, 0x40, + 0x2d, 0x06, 0x01, 0x03, 0x00, 0x01, 0x02, 0x03, 0x01, 0x67, 0x00, 0x04, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, + 0x4d, 0x05, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x0e, 0x0d, 0x00, 0x00, 0x13, 0x11, 0x0d, 0x14, 0x0e, 0x14, 0x00, + 0x0c, 0x00, 0x0c, 0x26, 0x21, 0x07, 0x0d, 0x18, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, + 0x23, 0x23, 0x07, 0x13, 0x32, 0x36, 0x35, 0x34, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xc7, 0x57, 0x69, 0x2f, 0x52, 0x8c, + 0x59, 0x4c, 0x35, 0x8d, 0x43, 0x52, 0x5f, 0x46, 0x2d, 0x02, 0xca, 0x34, 0x5e, 0x3e, 0x55, 0x70, 0x37, 0xfe, 0x01, + 0x7a, 0x42, 0x3a, 0x58, 0xd4, 0x00, 0x00, 0x02, 0x00, 0x3b, 0xff, 0x56, 0x02, 0xbc, 0x02, 0xd5, 0x00, 0x14, 0x00, + 0x23, 0x00, 0x32, 0x40, 0x2f, 0x12, 0x01, 0x00, 0x03, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x02, 0x86, 0x00, 0x04, 0x04, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x70, 0x4d, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x00, 0x4e, + 0x16, 0x15, 0x1e, 0x1c, 0x15, 0x23, 0x16, 0x23, 0x17, 0x26, 0x40, 0x06, 0x0d, 0x19, 0x2b, 0x05, 0x22, 0x22, 0x23, + 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x07, 0x17, 0x23, 0x03, 0x32, 0x3e, + 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0x16, 0x01, 0x4e, 0x03, 0x07, 0x03, 0x7f, 0x87, 0x30, + 0x5f, 0x8e, 0x5e, 0x7e, 0x88, 0x32, 0x64, 0x4a, 0x7b, 0xaf, 0x58, 0x30, 0x4d, 0x37, 0x1d, 0x3f, 0x38, 0x3f, 0x60, + 0x35, 0x41, 0x0a, 0x96, 0x7e, 0x57, 0xa4, 0x83, 0x4d, 0x96, 0x7f, 0x5a, 0xa8, 0x83, 0x22, 0xc3, 0x01, 0x21, 0x34, + 0x5c, 0x76, 0x43, 0x48, 0x4d, 0x5b, 0x96, 0x5b, 0x46, 0x4c, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x52, 0x02, + 0xca, 0x00, 0x0d, 0x00, 0x16, 0x00, 0x38, 0x40, 0x35, 0x08, 0x01, 0x02, 0x04, 0x01, 0x4c, 0x07, 0x01, 0x04, 0x00, + 0x02, 0x01, 0x04, 0x02, 0x67, 0x00, 0x05, 0x05, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x06, 0x03, 0x02, 0x01, + 0x01, 0x6b, 0x01, 0x4e, 0x0f, 0x0e, 0x00, 0x00, 0x15, 0x13, 0x0e, 0x16, 0x0f, 0x16, 0x00, 0x0d, 0x00, 0x0d, 0x11, + 0x16, 0x21, 0x08, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x13, 0x23, 0x03, 0x23, + 0x03, 0x13, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x23, 0x07, 0x1a, 0x97, 0xb0, 0x76, 0x7b, 0x57, 0x43, 0x7d, 0xa5, + 0x62, 0x43, 0x3a, 0x81, 0x3e, 0x4a, 0x2d, 0x31, 0x2d, 0x2b, 0x02, 0xca, 0x5f, 0x5f, 0x5a, 0x6a, 0x17, 0xfe, 0xcf, + 0x01, 0x12, 0xfe, 0xee, 0x01, 0x88, 0x3e, 0x3c, 0x27, 0x2a, 0xcb, 0x00, 0x01, 0x00, 0x14, 0xff, 0xf6, 0x02, 0x1e, + 0x02, 0xd4, 0x00, 0x27, 0x00, 0x37, 0x40, 0x34, 0x18, 0x01, 0x03, 0x02, 0x19, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x70, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x16, 0x14, 0x08, 0x06, 0x00, 0x27, 0x01, 0x27, + 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x2e, + 0x02, 0x35, 0x34, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x06, 0xc2, 0x36, 0x59, 0x1f, 0x2c, 0x56, 0x2d, 0x32, 0x42, 0x30, 0x26, 0x1e, 0x38, 0x24, + 0x3c, 0x6f, 0x4a, 0x38, 0x5e, 0x2c, 0x35, 0x4c, 0x41, 0x28, 0x34, 0x2e, 0x2a, 0x3b, 0x3b, 0x49, 0x79, 0x0a, 0x18, + 0x14, 0x86, 0x19, 0x1c, 0x26, 0x28, 0x29, 0x2f, 0x1c, 0x16, 0x36, 0x49, 0x31, 0x40, 0x61, 0x38, 0x18, 0x18, 0x72, + 0x24, 0x2b, 0x25, 0x26, 0x2d, 0x1c, 0x27, 0x5e, 0x3f, 0x4b, 0x62, 0x30, 0x00, 0x01, 0x00, 0x51, 0x00, 0x00, 0x02, + 0x5b, 0x02, 0xca, 0x00, 0x07, 0x00, 0x21, 0x40, 0x1e, 0x02, 0x01, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, + 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, + 0x19, 0x2b, 0x33, 0x13, 0x23, 0x37, 0x21, 0x07, 0x23, 0x03, 0x81, 0x7b, 0xab, 0x1c, 0x01, 0xee, 0x1c, 0xab, 0x7b, + 0x02, 0x4b, 0x7f, 0x7f, 0xfd, 0xb5, 0x00, 0x01, 0x00, 0x44, 0xff, 0xf6, 0x02, 0xbc, 0x02, 0xca, 0x00, 0x17, 0x00, + 0x24, 0x40, 0x21, 0x03, 0x01, 0x01, 0x01, 0x6a, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x01, 0x00, 0x13, 0x12, 0x0f, 0x0d, 0x08, 0x07, 0x00, 0x17, 0x01, 0x17, 0x05, 0x0d, 0x16, 0x2b, 0x05, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x33, + 0x03, 0x0e, 0x02, 0x01, 0x2b, 0x70, 0x77, 0x04, 0x04, 0x5f, 0x98, 0x5f, 0x08, 0x2e, 0x2e, 0x3c, 0x41, 0x11, 0x5f, + 0x97, 0x62, 0x12, 0x48, 0x79, 0x0a, 0x6f, 0x5c, 0x10, 0x29, 0x15, 0x01, 0xbb, 0xfe, 0x46, 0x27, 0x1e, 0x28, 0x2d, + 0x48, 0x4d, 0x01, 0xbf, 0xfe, 0x33, 0x54, 0x75, 0x3e, 0x00, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x02, 0xa8, 0x02, + 0xca, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, + 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, + 0x33, 0x03, 0x33, 0x13, 0x16, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x98, 0x3e, 0x90, 0x19, 0x02, + 0x01, 0x02, 0x04, 0x0b, 0x1b, 0x10, 0xd2, 0x9a, 0xfe, 0x93, 0x02, 0xca, 0xfe, 0x52, 0x1f, 0x4e, 0x1d, 0x21, 0x47, + 0x22, 0x01, 0xae, 0xfd, 0x36, 0x00, 0x01, 0x00, 0x5a, 0x00, 0x00, 0x03, 0xdc, 0x02, 0xca, 0x00, 0x22, 0x00, 0x27, + 0x40, 0x24, 0x1e, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, 0x02, 0x00, 0x00, 0x6a, 0x4d, 0x05, 0x04, + 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x22, 0x11, 0x1a, 0x19, 0x11, 0x06, 0x0d, 0x1a, + 0x2b, 0x33, 0x03, 0x33, 0x13, 0x14, 0x06, 0x07, 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x13, 0x16, 0x06, 0x06, 0x07, + 0x33, 0x36, 0x36, 0x37, 0x13, 0x33, 0x01, 0x23, 0x03, 0x26, 0x26, 0x34, 0x37, 0x23, 0x06, 0x07, 0x03, 0x70, 0x16, + 0x8c, 0x03, 0x03, 0x04, 0x04, 0x0e, 0x22, 0x0d, 0xb4, 0x84, 0x0a, 0x01, 0x01, 0x02, 0x02, 0x04, 0x0e, 0x23, 0x0e, + 0xa1, 0x97, 0xfe, 0xc4, 0xa9, 0x08, 0x01, 0x01, 0x01, 0x04, 0x1a, 0x1d, 0x9e, 0x02, 0xca, 0xfe, 0x7a, 0x25, 0x5d, + 0x27, 0x27, 0x59, 0x1f, 0x01, 0x90, 0xfe, 0x70, 0x11, 0x36, 0x3d, 0x1b, 0x29, 0x5f, 0x22, 0x01, 0x85, 0xfd, 0x36, + 0x01, 0x45, 0x2c, 0x39, 0x2e, 0x19, 0x50, 0x42, 0xfe, 0xa1, 0x00, 0x00, 0x01, 0xff, 0xc7, 0x00, 0x00, 0x02, 0xb0, + 0x02, 0xca, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, + 0x00, 0x00, 0x6a, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, + 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x01, 0x03, 0x33, 0x17, 0x37, 0x33, 0x01, 0x13, 0x23, 0x03, 0x03, 0x39, + 0x01, 0x19, 0x74, 0x9f, 0x4a, 0xaf, 0xac, 0xfe, 0xf6, 0x83, 0xa6, 0x53, 0xbf, 0x01, 0x7b, 0x01, 0x4f, 0xf6, 0xf6, + 0xfe, 0xa3, 0xfe, 0x93, 0x01, 0x0d, 0xfe, 0xf3, 0x00, 0x01, 0x00, 0x5b, 0x00, 0x00, 0x02, 0x90, 0x02, 0xca, 0x00, + 0x08, 0x00, 0x22, 0x40, 0x1f, 0x04, 0x01, 0x02, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6a, 0x4d, 0x03, + 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x12, 0x12, 0x04, 0x0d, 0x18, 0x2b, 0x33, + 0x13, 0x03, 0x33, 0x13, 0x13, 0x33, 0x01, 0x03, 0x94, 0x3a, 0x73, 0x98, 0x3f, 0xb7, 0xa7, 0xfe, 0xd2, 0x3a, 0x01, + 0x11, 0x01, 0xb9, 0xfe, 0xdf, 0x01, 0x21, 0xfe, 0x47, 0xfe, 0xef, 0x00, 0x00, 0x01, 0xff, 0xe2, 0x00, 0x00, 0x02, + 0x4a, 0x02, 0xca, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x01, 0x01, 0x6a, 0x4d, + 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, + 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x21, 0x37, 0x21, 0x07, 0x01, 0x21, 0x07, 0x1e, 0x13, 0x01, + 0x7b, 0xfe, 0xf7, 0x1a, 0x01, 0xc9, 0x14, 0xfe, 0x82, 0x01, 0x23, 0x1a, 0x62, 0x01, 0xeb, 0x7d, 0x63, 0xfe, 0x16, + 0x7d, 0x00, 0x01, 0xff, 0xee, 0xff, 0x62, 0x01, 0x8f, 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x02, + 0x04, 0x01, 0x03, 0x02, 0x03, 0x63, 0x00, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6a, 0x01, 0x4e, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x23, 0x03, 0x33, 0x07, + 0x12, 0xba, 0xe7, 0x16, 0x69, 0x8e, 0x69, 0x16, 0x9e, 0x03, 0x68, 0x67, 0xfd, 0x66, 0x67, 0x00, 0x00, 0x01, 0x00, + 0x6c, 0xff, 0xfa, 0x01, 0x5a, 0x02, 0xd0, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, + 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x03, + 0x33, 0x13, 0xdc, 0x70, 0x7b, 0x73, 0x06, 0x02, 0xd6, 0xfd, 0x2a, 0x00, 0x01, 0xff, 0xbd, 0xff, 0x62, 0x01, 0x5d, + 0x02, 0xca, 0x00, 0x07, 0x00, 0x22, 0x40, 0x1f, 0x00, 0x00, 0x04, 0x01, 0x03, 0x00, 0x03, 0x63, 0x00, 0x01, 0x01, + 0x02, 0x5f, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x11, 0x11, 0x11, 0x05, 0x0d, + 0x19, 0x2b, 0x07, 0x37, 0x33, 0x13, 0x23, 0x37, 0x33, 0x03, 0x43, 0x16, 0x68, 0x8e, 0x69, 0x16, 0xe7, 0xba, 0x9e, + 0x67, 0x02, 0x9a, 0x67, 0xfc, 0x98, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0xfe, 0x02, 0x0e, 0x02, 0xce, 0x00, 0x06, + 0x00, 0x27, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1c, 0x05, 0x01, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x00, 0x85, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x76, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0xb1, + 0x06, 0x00, 0x44, 0x37, 0x01, 0x33, 0x13, 0x23, 0x03, 0x03, 0x11, 0x01, 0x2e, 0x48, 0x87, 0x6d, 0x55, 0xc4, 0xfe, + 0x01, 0xd0, 0xfe, 0x30, 0x01, 0x35, 0xfe, 0xcb, 0x00, 0x00, 0x01, 0xff, 0xa5, 0xff, 0x62, 0x01, 0x45, 0xff, 0xa6, + 0x00, 0x03, 0x00, 0x26, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x1b, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x5f, 0x02, 0x01, 0x01, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x07, 0x37, 0x21, 0x07, 0x5b, 0x0f, 0x01, 0x91, 0x0f, 0x9e, 0x44, 0x44, 0x00, 0x01, 0x00, + 0x91, 0x02, 0x5e, 0x01, 0x63, 0x02, 0xfe, 0x00, 0x09, 0x00, 0x2d, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x22, 0x08, 0x04, + 0x02, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x02, 0x01, 0x01, + 0x00, 0x01, 0x4f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09, 0x15, 0x03, 0x0d, 0x17, 0x2b, 0xb1, 0x06, 0x00, 0x44, 0x01, + 0x2e, 0x02, 0x27, 0x35, 0x33, 0x16, 0x17, 0x15, 0x01, 0x07, 0x15, 0x2e, 0x28, 0x0b, 0x9a, 0x11, 0x27, 0x02, 0x5e, + 0x14, 0x34, 0x37, 0x17, 0x0a, 0x48, 0x4c, 0x0c, 0x00, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x42, 0x02, 0x2c, + 0x00, 0x15, 0x00, 0x24, 0x00, 0x7e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x12, 0x01, + 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x02, 0x12, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x19, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, + 0x04, 0x04, 0x00, 0x61, 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6d, + 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, + 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x17, 0x16, 0x01, 0x00, 0x20, 0x1e, + 0x16, 0x24, 0x17, 0x24, 0x11, 0x10, 0x0f, 0x0e, 0x0a, 0x08, 0x00, 0x15, 0x01, 0x15, 0x08, 0x0d, 0x16, 0x2b, 0x17, + 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, + 0x06, 0x37, 0x32, 0x36, 0x36, 0x37, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, 0x14, 0xc4, 0x2b, 0x45, + 0x28, 0x21, 0x40, 0x5e, 0x3d, 0x32, 0x3e, 0x13, 0x04, 0x1d, 0x76, 0x74, 0x77, 0x08, 0x04, 0x1b, 0x48, 0x07, 0x1b, + 0x32, 0x26, 0x0a, 0x09, 0x21, 0x1d, 0x24, 0x3b, 0x23, 0x0a, 0x29, 0x58, 0x47, 0x3c, 0x80, 0x6e, 0x44, 0x30, 0x23, + 0x49, 0xfd, 0xde, 0x4b, 0x24, 0x31, 0x79, 0x2d, 0x4a, 0x2d, 0x29, 0x22, 0x26, 0x2f, 0x46, 0x6d, 0x3c, 0x55, 0x00, + 0x00, 0x02, 0x00, 0x12, 0xff, 0xf6, 0x02, 0x27, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, 0x19, + 0x50, 0x58, 0x40, 0x0a, 0x0d, 0x01, 0x05, 0x03, 0x03, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0d, 0x01, + 0x05, 0x03, 0x03, 0x01, 0x01, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x02, + 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x01, + 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, + 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x22, 0x20, 0x1a, 0x28, 0x1b, 0x28, 0x12, + 0x10, 0x08, 0x07, 0x06, 0x05, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x27, 0x23, 0x07, + 0x23, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, + 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, 0x2a, 0x34, 0x41, 0x12, 0x04, 0x1c, + 0x71, 0xa1, 0x93, 0x1e, 0x04, 0x0e, 0x10, 0x07, 0x04, 0x1a, 0x3e, 0x32, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, 0x53, + 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, 0x25, 0x0a, 0x2c, 0x24, 0x46, 0x02, 0xf8, 0x8d, 0x14, 0x35, + 0x35, 0x14, 0x21, 0x32, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x77, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4f, + 0x52, 0x1d, 0x27, 0x2f, 0x00, 0x00, 0x01, 0x00, 0x2c, 0xff, 0xf6, 0x01, 0xef, 0x02, 0x2c, 0x00, 0x1e, 0x00, 0x37, + 0x40, 0x34, 0x0c, 0x01, 0x02, 0x01, 0x1b, 0x0d, 0x02, 0x03, 0x02, 0x1c, 0x01, 0x00, 0x03, 0x03, 0x4c, 0x00, 0x02, + 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, + 0x4e, 0x01, 0x00, 0x19, 0x17, 0x11, 0x0f, 0x0a, 0x08, 0x00, 0x1e, 0x01, 0x1e, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, 0xf7, 0x39, 0x5c, 0x36, 0x28, 0x4c, 0x6b, 0x42, 0x2e, 0x4f, 0x25, + 0x2f, 0x17, 0x39, 0x1d, 0x22, 0x36, 0x25, 0x13, 0x2c, 0x27, 0x23, 0x41, 0x22, 0x22, 0x50, 0x0a, 0x2d, 0x60, 0x4b, + 0x49, 0x7f, 0x60, 0x36, 0x11, 0x11, 0x71, 0x0a, 0x11, 0x28, 0x41, 0x4f, 0x26, 0x36, 0x31, 0x16, 0x11, 0x79, 0x12, + 0x15, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x6e, 0x02, 0xf8, 0x00, 0x19, 0x00, 0x28, 0x00, 0x82, 0x4b, 0xb0, + 0x19, 0x50, 0x58, 0x40, 0x0a, 0x0c, 0x01, 0x05, 0x01, 0x16, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x0c, + 0x01, 0x05, 0x01, 0x16, 0x01, 0x03, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, + 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, + 0x03, 0x06, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x02, 0x02, 0x6c, 0x4d, 0x00, 0x05, 0x05, + 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x6b, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x17, 0x1b, 0x1a, 0x01, 0x00, 0x23, 0x21, 0x1a, 0x28, 0x1b, 0x28, + 0x15, 0x14, 0x13, 0x12, 0x0a, 0x08, 0x00, 0x19, 0x01, 0x19, 0x08, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x34, 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, + 0x06, 0x37, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xc6, 0x27, 0x47, 0x2c, 0x24, + 0x42, 0x5d, 0x3a, 0x31, 0x38, 0x13, 0x04, 0x03, 0x06, 0x04, 0x25, 0x93, 0xa1, 0x70, 0x09, 0x04, 0x1d, 0x4a, 0x09, + 0x23, 0x31, 0x1f, 0x0f, 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x0a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, + 0x22, 0x03, 0x25, 0x31, 0x14, 0xaf, 0xfd, 0x08, 0x47, 0x24, 0x2d, 0x77, 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, + 0x46, 0x56, 0x2b, 0x56, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x14, 0x02, 0x2c, 0x00, 0x1b, 0x00, 0x25, 0x00, + 0x43, 0x40, 0x40, 0x18, 0x01, 0x03, 0x02, 0x19, 0x01, 0x00, 0x03, 0x02, 0x4c, 0x07, 0x01, 0x04, 0x00, 0x02, 0x03, + 0x04, 0x02, 0x69, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x00, 0x03, 0x03, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1d, 0x1c, 0x01, 0x00, 0x22, 0x20, 0x1c, 0x25, 0x1d, 0x25, 0x16, 0x14, 0x0f, + 0x0d, 0x09, 0x07, 0x00, 0x1b, 0x01, 0x1b, 0x08, 0x0d, 0x16, 0x2b, 0x05, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x23, 0x23, 0x06, 0x14, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x06, + 0x03, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x01, 0x04, 0x60, 0x78, 0x27, 0x4d, 0x72, 0x4b, 0x5c, + 0x5b, 0x9b, 0x9f, 0x19, 0x01, 0x33, 0x2e, 0x2b, 0x46, 0x30, 0x2b, 0x58, 0x58, 0x55, 0x4b, 0x33, 0x1b, 0x36, 0x29, + 0x09, 0x0a, 0x69, 0x6a, 0x45, 0x7f, 0x64, 0x3b, 0x54, 0x41, 0x56, 0x68, 0x06, 0x09, 0x05, 0x2c, 0x34, 0x14, 0x16, + 0x6f, 0x15, 0x15, 0x01, 0x46, 0x35, 0x23, 0x2e, 0x22, 0x3c, 0x28, 0x00, 0x01, 0xff, 0x96, 0xff, 0x10, 0x01, 0xe5, + 0x02, 0xfd, 0x00, 0x23, 0x00, 0xa3, 0x40, 0x12, 0x15, 0x01, 0x04, 0x03, 0x16, 0x01, 0x05, 0x04, 0x04, 0x01, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, 0x61, + 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, 0x01, + 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x21, 0x00, 0x04, + 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6c, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, + 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x04, 0x04, 0x03, + 0x61, 0x00, 0x03, 0x03, 0x72, 0x4d, 0x06, 0x01, 0x02, 0x02, 0x05, 0x5f, 0x00, 0x05, 0x05, 0x6d, 0x4d, 0x00, 0x01, + 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x40, 0x15, 0x01, 0x00, 0x20, 0x1f, 0x1e, + 0x1d, 0x1a, 0x18, 0x13, 0x11, 0x0c, 0x0b, 0x08, 0x06, 0x00, 0x23, 0x01, 0x23, 0x08, 0x0d, 0x16, 0x2b, 0x07, 0x22, + 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x06, 0x13, 0x18, 0x2f, 0x10, 0x0e, + 0x1c, 0x0f, 0x24, 0x26, 0x09, 0x63, 0x55, 0x0f, 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, + 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, 0x69, 0x11, 0x5a, 0xf0, 0x07, 0x05, 0x77, 0x04, 0x06, 0x29, 0x29, + 0x01, 0xd7, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x13, 0x51, + 0x64, 0x00, 0x00, 0x02, 0x00, 0x12, 0xff, 0x10, 0x02, 0x42, 0x02, 0x2c, 0x00, 0x23, 0x00, 0x32, 0x00, 0x9e, 0x4b, + 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x03, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, 0x12, 0x1c, 0x01, 0x06, 0x04, 0x0d, 0x01, 0x02, 0x05, 0x04, 0x01, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x22, 0x00, 0x06, 0x06, 0x03, + 0x61, 0x04, 0x01, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x00, + 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, 0x26, 0x00, 0x04, 0x04, 0x6d, 0x4d, + 0x00, 0x06, 0x06, 0x03, 0x61, 0x00, 0x03, 0x03, 0x73, 0x4d, 0x08, 0x01, 0x05, 0x05, 0x02, 0x61, 0x00, 0x02, 0x02, + 0x71, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, 0x07, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x40, 0x19, 0x25, 0x24, + 0x01, 0x00, 0x2d, 0x2b, 0x24, 0x32, 0x25, 0x32, 0x1f, 0x1e, 0x1a, 0x18, 0x12, 0x10, 0x08, 0x06, 0x00, 0x23, 0x01, + 0x23, 0x09, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x37, 0x37, 0x36, 0x36, 0x37, + 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, 0x37, 0x33, 0x03, 0x0e, + 0x02, 0x11, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xbd, 0x38, 0x53, 0x20, 0x21, + 0x58, 0x2e, 0x67, 0x18, 0x07, 0x03, 0x0a, 0x05, 0x04, 0x1a, 0x43, 0x32, 0x40, 0x52, 0x20, 0x3f, 0x5e, 0x3f, 0x32, + 0x3b, 0x16, 0x04, 0x1d, 0x76, 0x78, 0x12, 0x4c, 0x6d, 0x1b, 0x30, 0x25, 0x16, 0x1d, 0x21, 0x1c, 0x2f, 0x24, 0x13, + 0xf0, 0x13, 0x0d, 0x7e, 0x12, 0x18, 0x63, 0x1c, 0x0f, 0x27, 0x0f, 0x21, 0x2e, 0x5c, 0x68, 0x3c, 0x80, 0x6f, 0x44, + 0x2c, 0x27, 0x49, 0xfd, 0xca, 0x52, 0x60, 0x2a, 0x01, 0x5f, 0x2b, 0x47, 0x54, 0x29, 0x26, 0x2f, 0x29, 0x45, 0x55, + 0x2c, 0x55, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0xf8, 0x00, 0x1c, 0x00, 0x2d, 0x40, 0x2a, 0x07, + 0x01, 0x03, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x24, 0x15, 0x28, 0x11, + 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x0e, 0x02, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x1c, 0x04, 0x10, + 0x10, 0x07, 0x04, 0x1e, 0x4a, 0x31, 0x47, 0x46, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, + 0x02, 0xf8, 0x84, 0x16, 0x3a, 0x37, 0x14, 0x26, 0x2d, 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, + 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x12, 0x00, 0x00, 0x01, 0x41, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x0f, + 0x00, 0x2d, 0x40, 0x2a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x02, 0x02, 0x6d, + 0x4d, 0x05, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x0c, 0x0c, 0x01, 0x00, 0x0c, 0x0f, 0x0c, 0x0f, 0x0e, 0x0d, 0x07, + 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x06, 0x0d, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, + 0x14, 0x06, 0x01, 0x13, 0x33, 0x03, 0xe8, 0x21, 0x2b, 0x30, 0x2b, 0x20, 0x2a, 0x2f, 0xff, 0x00, 0x73, 0x97, 0x75, + 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, 0x20, 0x28, 0x30, 0xfd, 0x9b, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, + 0x80, 0xff, 0x10, 0x01, 0x43, 0x02, 0xf9, 0x00, 0x0b, 0x00, 0x1b, 0x00, 0x3e, 0x40, 0x3b, 0x10, 0x01, 0x03, 0x04, + 0x0f, 0x01, 0x02, 0x03, 0x02, 0x4c, 0x05, 0x01, 0x00, 0x00, 0x01, 0x61, 0x00, 0x01, 0x01, 0x72, 0x4d, 0x00, 0x04, + 0x04, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x02, 0x61, 0x06, 0x01, 0x02, 0x02, 0x6f, 0x02, 0x4e, 0x0d, 0x0c, 0x01, 0x00, + 0x17, 0x16, 0x13, 0x11, 0x0c, 0x1b, 0x0d, 0x1b, 0x07, 0x05, 0x00, 0x0b, 0x01, 0x0b, 0x07, 0x0d, 0x16, 0x2b, 0x13, + 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, 0x22, 0x26, 0x27, 0x35, 0x16, 0x33, 0x32, + 0x36, 0x37, 0x13, 0x33, 0x03, 0x0e, 0x02, 0xea, 0x20, 0x2b, 0x2f, 0x2b, 0x20, 0x2a, 0x2f, 0xfe, 0xc2, 0x17, 0x30, + 0x0f, 0x1c, 0x1c, 0x1e, 0x2d, 0x09, 0x7c, 0x95, 0x80, 0x0b, 0x2e, 0x50, 0x02, 0x65, 0x1d, 0x20, 0x28, 0x2f, 0x1c, + 0x20, 0x28, 0x30, 0xfc, 0xab, 0x07, 0x05, 0x77, 0x0a, 0x27, 0x2b, 0x02, 0x47, 0xfd, 0xa4, 0x32, 0x53, 0x31, 0x00, + 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x69, 0x02, 0xf8, 0x00, 0x0f, 0x00, 0x29, 0x40, 0x26, 0x0d, 0x0a, 0x06, 0x03, + 0x02, 0x01, 0x01, 0x4c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x12, 0x16, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, 0x33, + 0x03, 0x06, 0x06, 0x07, 0x33, 0x37, 0x33, 0x07, 0x13, 0x23, 0x27, 0x07, 0x07, 0x12, 0xa1, 0x93, 0x48, 0x05, 0x14, + 0x05, 0x04, 0xdd, 0xa8, 0xf3, 0x8b, 0xa4, 0x59, 0x3b, 0x24, 0x02, 0xf8, 0xfe, 0xad, 0x19, 0x41, 0x11, 0xe8, 0xf6, + 0xfe, 0xd4, 0xcd, 0x23, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01, 0x48, 0x02, 0xf8, 0x00, 0x03, 0x00, + 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x33, 0x13, 0x33, 0x03, 0x11, 0xa2, 0x95, 0xa1, 0x02, 0xf8, 0xfd, 0x08, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x03, 0x56, 0x02, 0x2c, 0x00, 0x2a, 0x00, 0x56, 0xb6, 0x0a, 0x03, 0x02, + 0x04, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x16, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x08, 0x07, 0x05, 0x03, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x1a, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x01, 0x61, 0x02, 0x01, 0x01, 0x01, 0x73, 0x4d, 0x08, 0x07, 0x05, 0x03, + 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x59, 0x40, 0x10, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x2a, 0x24, 0x14, 0x24, 0x15, 0x25, + 0x24, 0x11, 0x09, 0x0d, 0x1d, 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, + 0x23, 0x13, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, + 0x38, 0x3e, 0x0a, 0x04, 0x1f, 0x56, 0x39, 0x44, 0x44, 0x0b, 0x41, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x28, 0x0c, + 0x2f, 0x93, 0x43, 0x08, 0x30, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x3b, 0x34, 0x31, 0x3e, + 0x55, 0x48, 0x24, 0x34, 0xfe, 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x38, 0x5f, 0x3b, 0xe3, 0x01, 0x3f, 0x23, 0x17, + 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x02, 0x29, 0x02, 0x2c, 0x00, 0x18, 0x00, + 0x4c, 0xb5, 0x03, 0x01, 0x03, 0x00, 0x01, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x00, 0x03, 0x03, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x1b, 0x40, 0x17, 0x00, + 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x6b, 0x02, 0x4e, 0x59, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x24, 0x15, 0x24, 0x11, 0x06, 0x0d, 0x1a, + 0x2b, 0x33, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x03, 0x23, 0x13, 0x36, 0x35, + 0x34, 0x23, 0x22, 0x06, 0x06, 0x07, 0x07, 0x12, 0x74, 0x70, 0x0a, 0x04, 0x20, 0x53, 0x39, 0x47, 0x46, 0x0b, 0x41, + 0x93, 0x43, 0x08, 0x35, 0x21, 0x36, 0x27, 0x0d, 0x30, 0x02, 0x22, 0x65, 0x31, 0x3e, 0x55, 0x48, 0x24, 0x34, 0xfe, + 0xc9, 0x01, 0x3f, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0x00, 0x02, 0x00, 0x2c, 0xff, 0xf6, 0x02, 0x1d, 0x02, + 0x2c, 0x00, 0x10, 0x00, 0x1e, 0x00, 0x2d, 0x40, 0x2a, 0x00, 0x03, 0x03, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, + 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x12, 0x11, 0x01, 0x00, 0x19, 0x17, + 0x11, 0x1e, 0x12, 0x1e, 0x0a, 0x08, 0x00, 0x10, 0x01, 0x10, 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x26, 0x35, + 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, 0x0e, 0x02, 0x27, 0x32, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0xfd, 0x3d, 0x5f, 0x35, 0x24, 0x48, 0x6d, 0x49, 0x5f, 0x70, 0x22, 0x47, 0x6d, 0x3e, 0x29, + 0x39, 0x1e, 0x1f, 0x27, 0x21, 0x32, 0x20, 0x10, 0x0a, 0x33, 0x5e, 0x41, 0x48, 0x81, 0x63, 0x38, 0x72, 0x66, 0x45, + 0x7e, 0x62, 0x39, 0x78, 0x42, 0x69, 0x3b, 0x29, 0x37, 0x2d, 0x48, 0x52, 0x25, 0x5a, 0x00, 0x00, 0x02, 0xff, 0xdf, + 0xff, 0x10, 0x02, 0x27, 0x02, 0x2c, 0x00, 0x18, 0x00, 0x27, 0x00, 0x6c, 0x40, 0x0a, 0x03, 0x01, 0x05, 0x00, 0x13, + 0x01, 0x02, 0x04, 0x02, 0x4c, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x01, 0x01, + 0x00, 0x00, 0x6d, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, + 0x6f, 0x03, 0x4e, 0x1b, 0x40, 0x21, 0x00, 0x00, 0x00, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, + 0x73, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x02, 0x61, 0x00, 0x02, 0x02, 0x71, 0x4d, 0x06, 0x01, 0x03, 0x03, 0x6f, 0x03, + 0x4e, 0x59, 0x40, 0x14, 0x1a, 0x19, 0x00, 0x00, 0x21, 0x1f, 0x19, 0x27, 0x1a, 0x27, 0x00, 0x18, 0x00, 0x18, 0x27, + 0x24, 0x11, 0x08, 0x0d, 0x19, 0x2b, 0x07, 0x13, 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x16, 0x15, 0x14, + 0x0e, 0x02, 0x23, 0x22, 0x26, 0x27, 0x23, 0x06, 0x06, 0x07, 0x07, 0x13, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, + 0x0e, 0x02, 0x15, 0x14, 0x16, 0x21, 0xa7, 0x70, 0x08, 0x04, 0x1a, 0x4c, 0x35, 0x28, 0x46, 0x2c, 0x24, 0x42, 0x5d, + 0x3a, 0x32, 0x36, 0x14, 0x04, 0x03, 0x0a, 0x08, 0x23, 0x9f, 0x1b, 0x2f, 0x23, 0x14, 0x40, 0x24, 0x32, 0x20, 0x0f, + 0x25, 0xf0, 0x03, 0x12, 0x53, 0x23, 0x3a, 0x27, 0x57, 0x49, 0x42, 0x83, 0x6a, 0x40, 0x2e, 0x22, 0x28, 0x42, 0x26, + 0xa6, 0x01, 0x5d, 0x2b, 0x46, 0x56, 0x2b, 0x56, 0x34, 0x4e, 0x52, 0x1e, 0x27, 0x2f, 0x00, 0x00, 0x02, 0x00, 0x2c, + 0xff, 0x10, 0x02, 0x41, 0x02, 0x2c, 0x00, 0x19, 0x00, 0x29, 0x00, 0x78, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0a, + 0x14, 0x01, 0x05, 0x01, 0x04, 0x01, 0x00, 0x04, 0x02, 0x4c, 0x1b, 0x40, 0x0a, 0x14, 0x01, 0x05, 0x02, 0x04, 0x01, + 0x00, 0x04, 0x02, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x1c, 0x00, 0x05, 0x05, 0x01, 0x61, 0x02, 0x01, + 0x01, 0x01, 0x73, 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, + 0x03, 0x4e, 0x1b, 0x40, 0x20, 0x00, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, + 0x4d, 0x06, 0x01, 0x04, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x71, 0x4d, 0x00, 0x03, 0x03, 0x6f, 0x03, 0x4e, 0x59, + 0x40, 0x0f, 0x1b, 0x1a, 0x23, 0x21, 0x1a, 0x29, 0x1b, 0x29, 0x11, 0x14, 0x27, 0x27, 0x07, 0x0d, 0x1a, 0x2b, 0x05, + 0x3e, 0x02, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x33, + 0x37, 0x33, 0x03, 0x23, 0x03, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x16, 0x01, + 0x2b, 0x04, 0x0e, 0x11, 0x06, 0x04, 0x1a, 0x44, 0x33, 0x24, 0x43, 0x2c, 0x24, 0x42, 0x5d, 0x3a, 0x31, 0x3e, 0x18, + 0x04, 0x1c, 0x71, 0xa7, 0x93, 0x02, 0x23, 0x31, 0x1e, 0x0f, 0x24, 0x20, 0x1b, 0x2f, 0x23, 0x14, 0x24, 0x4b, 0x12, + 0x35, 0x38, 0x15, 0x22, 0x31, 0x27, 0x57, 0x48, 0x43, 0x82, 0x6b, 0x40, 0x2a, 0x26, 0x46, 0xfc, 0xee, 0x01, 0x5d, + 0x35, 0x4f, 0x51, 0x1d, 0x27, 0x2f, 0x2b, 0x46, 0x56, 0x2b, 0x2b, 0x2b, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x01, + 0xcc, 0x02, 0x2c, 0x00, 0x12, 0x00, 0x69, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x0e, 0x03, 0x01, 0x02, 0x00, 0x0b, + 0x01, 0x03, 0x02, 0x02, 0x4c, 0x0a, 0x01, 0x00, 0x4a, 0x1b, 0x40, 0x0e, 0x0a, 0x01, 0x00, 0x01, 0x03, 0x01, 0x02, + 0x00, 0x0b, 0x01, 0x03, 0x02, 0x03, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x12, 0x00, 0x02, 0x02, 0x00, + 0x61, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x1b, 0x40, 0x16, 0x00, 0x00, + 0x00, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, 0x01, 0x01, 0x73, 0x4d, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, + 0x4e, 0x59, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x25, 0x24, 0x11, 0x05, 0x0d, 0x19, 0x2b, 0x33, 0x13, + 0x33, 0x07, 0x33, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x12, 0x73, + 0x79, 0x0a, 0x04, 0x22, 0x4b, 0x38, 0x0c, 0x1a, 0x09, 0x21, 0x0c, 0x1c, 0x10, 0x39, 0x4e, 0x11, 0x34, 0x02, 0x22, + 0x5e, 0x33, 0x35, 0x02, 0x03, 0x91, 0x04, 0x05, 0x5c, 0x4f, 0xf4, 0x00, 0x01, 0x00, 0x0b, 0xff, 0xf6, 0x01, 0xc7, + 0x02, 0x2c, 0x00, 0x26, 0x00, 0x37, 0x40, 0x34, 0x17, 0x01, 0x03, 0x02, 0x18, 0x04, 0x02, 0x01, 0x03, 0x03, 0x01, + 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x03, 0x02, 0x61, 0x00, 0x02, 0x02, 0x73, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x01, 0x00, 0x1c, 0x1a, 0x15, 0x13, 0x08, 0x06, 0x00, 0x26, 0x01, 0x26, + 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x26, 0x27, + 0x26, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x17, + 0x16, 0x16, 0x15, 0x14, 0x06, 0xb0, 0x35, 0x51, 0x1f, 0x25, 0x4f, 0x28, 0x22, 0x36, 0x0d, 0x23, 0x22, 0x36, 0x33, + 0x6a, 0x67, 0x34, 0x58, 0x26, 0x2f, 0x1b, 0x44, 0x22, 0x1c, 0x20, 0x21, 0x29, 0x37, 0x3b, 0x7e, 0x0a, 0x11, 0x0f, + 0x7c, 0x15, 0x16, 0x19, 0x1c, 0x0f, 0x16, 0x1a, 0x13, 0x1d, 0x47, 0x34, 0x4b, 0x5b, 0x18, 0x16, 0x66, 0x10, 0x19, + 0x1a, 0x17, 0x13, 0x1c, 0x16, 0x1c, 0x48, 0x35, 0x5f, 0x5d, 0x00, 0x01, 0x00, 0x2e, 0xff, 0xf6, 0x01, 0xad, 0x02, + 0x96, 0x00, 0x1b, 0x00, 0x66, 0x40, 0x0a, 0x18, 0x01, 0x05, 0x01, 0x19, 0x01, 0x00, 0x05, 0x02, 0x4c, 0x4b, 0xb0, + 0x0a, 0x50, 0x58, 0x40, 0x1d, 0x00, 0x02, 0x03, 0x03, 0x02, 0x70, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, + 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x1c, 0x00, + 0x02, 0x03, 0x02, 0x85, 0x04, 0x01, 0x01, 0x01, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x6d, 0x4d, 0x00, 0x05, 0x05, 0x00, + 0x61, 0x06, 0x01, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x59, 0x40, 0x13, 0x01, 0x00, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x07, 0x06, 0x00, 0x1b, 0x01, 0x1b, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x37, 0x13, + 0x23, 0x3f, 0x02, 0x33, 0x07, 0x33, 0x07, 0x23, 0x03, 0x06, 0x15, 0x14, 0x16, 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, + 0x06, 0xc8, 0x40, 0x4e, 0x06, 0x38, 0x4a, 0x0e, 0x60, 0x40, 0x5f, 0x18, 0x8a, 0x18, 0x8a, 0x38, 0x03, 0x18, 0x13, + 0x14, 0x25, 0x16, 0x17, 0x42, 0x0a, 0x37, 0x47, 0x19, 0x1e, 0x01, 0x07, 0x48, 0x29, 0x73, 0x74, 0x70, 0xfe, 0xf9, + 0x0f, 0x0b, 0x13, 0x11, 0x09, 0x08, 0x6e, 0x0b, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x36, 0xff, 0xf6, 0x02, 0x4b, 0x02, + 0x22, 0x00, 0x19, 0x00, 0x5e, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0xb5, 0x16, 0x01, 0x00, 0x02, 0x01, 0x4c, 0x1b, 0xb5, + 0x16, 0x01, 0x04, 0x02, 0x01, 0x4c, 0x59, 0x4b, 0xb0, 0x19, 0x50, 0x58, 0x40, 0x13, 0x03, 0x01, 0x01, 0x01, 0x6d, + 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x04, 0x05, 0x02, 0x00, 0x00, 0x71, 0x00, 0x4e, 0x1b, 0x40, 0x17, 0x03, 0x01, + 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x04, 0x04, 0x6b, 0x4d, 0x00, 0x02, 0x02, 0x00, 0x62, 0x05, 0x01, 0x00, 0x00, 0x71, + 0x00, 0x4e, 0x59, 0x40, 0x11, 0x01, 0x00, 0x15, 0x14, 0x13, 0x12, 0x0e, 0x0c, 0x08, 0x07, 0x00, 0x19, 0x01, 0x19, + 0x06, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x13, 0x33, 0x03, 0x06, 0x15, 0x14, 0x33, 0x32, + 0x36, 0x36, 0x37, 0x37, 0x33, 0x03, 0x23, 0x37, 0x23, 0x06, 0x06, 0xc1, 0x46, 0x45, 0x06, 0x06, 0x3e, 0x93, 0x43, + 0x08, 0x35, 0x22, 0x35, 0x28, 0x0c, 0x30, 0x93, 0x74, 0x70, 0x0a, 0x05, 0x1f, 0x53, 0x0a, 0x55, 0x48, 0x12, 0x39, + 0x1d, 0x01, 0x27, 0xfe, 0xc1, 0x23, 0x17, 0x3c, 0x39, 0x60, 0x3a, 0xe2, 0xfd, 0xde, 0x65, 0x31, 0x3e, 0x00, 0x01, + 0x00, 0x32, 0x00, 0x00, 0x02, 0x3a, 0x02, 0x22, 0x00, 0x0d, 0x00, 0x21, 0x40, 0x1e, 0x06, 0x01, 0x02, 0x00, 0x01, + 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x03, 0x01, 0x02, 0x02, 0x6b, 0x02, 0x4e, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x0d, 0x19, 0x11, 0x04, 0x0d, 0x18, 0x2b, 0x33, 0x03, 0x33, 0x13, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, 0x13, + 0x33, 0x01, 0x75, 0x43, 0x90, 0x16, 0x02, 0x01, 0x05, 0x09, 0x18, 0x0a, 0x91, 0x9e, 0xfe, 0xd9, 0x02, 0x22, 0xfe, + 0xe2, 0x13, 0x43, 0x1b, 0x19, 0x41, 0x13, 0x01, 0x22, 0xfd, 0xde, 0x00, 0x00, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x03, + 0x47, 0x02, 0x22, 0x00, 0x25, 0x00, 0x27, 0x40, 0x24, 0x1f, 0x11, 0x06, 0x03, 0x03, 0x00, 0x01, 0x4c, 0x02, 0x01, + 0x02, 0x00, 0x00, 0x6d, 0x4d, 0x05, 0x04, 0x02, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, + 0x11, 0x1a, 0x1a, 0x11, 0x06, 0x0d, 0x1a, 0x2b, 0x33, 0x03, 0x33, 0x17, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, + 0x13, 0x33, 0x11, 0x14, 0x06, 0x07, 0x33, 0x3e, 0x02, 0x37, 0x37, 0x33, 0x01, 0x23, 0x27, 0x34, 0x36, 0x36, 0x37, + 0x23, 0x0e, 0x02, 0x07, 0x03, 0x56, 0x19, 0x89, 0x02, 0x01, 0x04, 0x04, 0x07, 0x16, 0x13, 0x04, 0x71, 0xa0, 0x01, + 0x04, 0x05, 0x07, 0x15, 0x16, 0x08, 0x6b, 0x96, 0xfe, 0xfd, 0xa1, 0x03, 0x01, 0x03, 0x01, 0x06, 0x08, 0x15, 0x14, + 0x08, 0x72, 0x02, 0x22, 0xf2, 0x28, 0x4f, 0x2e, 0x19, 0x3d, 0x32, 0x09, 0x01, 0x06, 0xfe, 0xfa, 0x22, 0x46, 0x29, + 0x17, 0x3e, 0x3d, 0x13, 0xf2, 0xfd, 0xde, 0xfe, 0x15, 0x3b, 0x3e, 0x18, 0x18, 0x3b, 0x36, 0x13, 0xfe, 0xf8, 0x00, + 0x01, 0xff, 0xce, 0x00, 0x00, 0x02, 0x47, 0x02, 0x22, 0x00, 0x0b, 0x00, 0x26, 0x40, 0x23, 0x0a, 0x07, 0x04, 0x01, + 0x04, 0x02, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x6d, 0x4d, 0x04, 0x03, 0x02, 0x02, 0x02, 0x6b, 0x02, 0x4e, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x0b, 0x12, 0x12, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x13, 0x03, 0x33, 0x17, 0x37, + 0x33, 0x03, 0x13, 0x23, 0x27, 0x07, 0x32, 0xe8, 0x6b, 0xa0, 0x37, 0x75, 0xb0, 0xe1, 0x73, 0xa2, 0x3b, 0x7f, 0x01, + 0x18, 0x01, 0x0a, 0xaa, 0xaa, 0xfe, 0xee, 0xfe, 0xf0, 0xb3, 0xb3, 0x00, 0x01, 0xff, 0xbb, 0xff, 0x10, 0x02, 0x3b, + 0x02, 0x22, 0x00, 0x1a, 0x00, 0x30, 0x40, 0x2d, 0x11, 0x0b, 0x04, 0x03, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x4c, 0x03, 0x01, 0x02, 0x02, 0x6d, 0x4d, 0x00, 0x01, 0x01, 0x00, 0x62, 0x04, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x4e, + 0x01, 0x00, 0x17, 0x16, 0x0d, 0x0c, 0x08, 0x06, 0x00, 0x1a, 0x01, 0x1a, 0x05, 0x0d, 0x16, 0x2b, 0x17, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x37, 0x37, 0x03, 0x33, 0x17, 0x16, 0x16, 0x15, 0x33, 0x36, 0x36, 0x37, + 0x13, 0x33, 0x01, 0x06, 0x06, 0x03, 0x1a, 0x22, 0x0c, 0x0d, 0x1b, 0x11, 0x2f, 0x3c, 0x16, 0x0d, 0x50, 0x90, 0x1b, + 0x04, 0x02, 0x04, 0x0a, 0x18, 0x13, 0x7f, 0xa0, 0xfe, 0xb4, 0x2c, 0x77, 0xf0, 0x05, 0x04, 0x75, 0x02, 0x04, 0x36, + 0x2a, 0x18, 0x02, 0x22, 0xfd, 0x22, 0x50, 0x1d, 0x19, 0x43, 0x29, 0x01, 0x07, 0xfd, 0x90, 0x53, 0x4f, 0x00, 0x00, + 0x01, 0xff, 0xee, 0x00, 0x00, 0x01, 0xdf, 0x02, 0x22, 0x00, 0x09, 0x00, 0x25, 0x40, 0x22, 0x00, 0x00, 0x00, 0x01, + 0x5f, 0x00, 0x01, 0x01, 0x6d, 0x4d, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, 0x01, 0x03, 0x03, 0x6b, 0x03, 0x4e, 0x00, + 0x00, 0x00, 0x09, 0x00, 0x09, 0x12, 0x11, 0x12, 0x05, 0x0d, 0x19, 0x2b, 0x23, 0x37, 0x01, 0x23, 0x37, 0x21, 0x07, + 0x01, 0x33, 0x07, 0x12, 0x11, 0x01, 0x18, 0xc2, 0x1a, 0x01, 0x70, 0x15, 0xfe, 0xed, 0xd5, 0x18, 0x59, 0x01, 0x57, + 0x72, 0x63, 0xfe, 0xb4, 0x73, 0x00, 0x01, 0xff, 0xff, 0xff, 0x62, 0x01, 0xa3, 0x02, 0xca, 0x00, 0x2c, 0x00, 0x37, + 0x40, 0x34, 0x1d, 0x01, 0x01, 0x02, 0x01, 0x4c, 0x00, 0x02, 0x00, 0x01, 0x05, 0x02, 0x01, 0x69, 0x00, 0x05, 0x06, + 0x01, 0x00, 0x05, 0x00, 0x65, 0x00, 0x04, 0x04, 0x03, 0x61, 0x00, 0x03, 0x03, 0x6a, 0x04, 0x4e, 0x01, 0x00, 0x2b, + 0x2a, 0x17, 0x16, 0x15, 0x13, 0x0e, 0x0d, 0x0c, 0x0b, 0x00, 0x2c, 0x01, 0x2c, 0x07, 0x0d, 0x16, 0x2b, 0x17, 0x22, + 0x26, 0x35, 0x34, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x37, 0x32, 0x36, 0x37, 0x37, 0x36, 0x36, 0x33, + 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x07, 0x07, 0x06, 0x06, + 0x15, 0x14, 0x16, 0x33, 0x15, 0xde, 0x56, 0x4d, 0x08, 0x14, 0x02, 0x03, 0x2a, 0x33, 0x17, 0x3b, 0x3c, 0x0a, 0x1d, + 0x11, 0x53, 0x5d, 0x2e, 0x18, 0x27, 0x2e, 0x09, 0x1d, 0x0c, 0x43, 0x36, 0x2a, 0x26, 0x04, 0x02, 0x13, 0x02, 0x03, + 0x21, 0x1e, 0x9e, 0x41, 0x3c, 0x1d, 0x24, 0x5c, 0x0a, 0x11, 0x07, 0x22, 0x22, 0x72, 0x28, 0x30, 0x86, 0x4c, 0x4c, + 0x70, 0x1b, 0x29, 0x8a, 0x36, 0x37, 0x07, 0x03, 0x0d, 0x38, 0x29, 0x0b, 0x18, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x19, + 0x14, 0x70, 0x00, 0x00, 0x01, 0x00, 0xde, 0xff, 0x1d, 0x01, 0x49, 0x02, 0xf5, 0x00, 0x03, 0x00, 0x30, 0x4b, 0xb0, + 0x27, 0x50, 0x58, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x6c, 0x4d, 0x02, 0x01, 0x01, 0x01, 0x6f, 0x01, 0x4e, 0x1b, 0x40, + 0x0c, 0x02, 0x01, 0x01, 0x01, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x4e, 0x59, 0x40, 0x0a, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x17, 0x11, 0x33, 0x11, 0xde, 0x6b, 0xe3, 0x03, 0xd8, 0xfc, 0x28, + 0x00, 0x00, 0x01, 0xff, 0xcd, 0xff, 0x62, 0x01, 0x65, 0x02, 0xca, 0x00, 0x2a, 0x00, 0x31, 0x40, 0x2e, 0x07, 0x01, + 0x04, 0x03, 0x01, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x00, 0x03, 0x04, 0x69, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x65, + 0x00, 0x01, 0x01, 0x02, 0x61, 0x00, 0x02, 0x02, 0x6a, 0x01, 0x4e, 0x2a, 0x28, 0x23, 0x22, 0x21, 0x20, 0x17, 0x15, + 0x14, 0x13, 0x10, 0x06, 0x0d, 0x17, 0x2b, 0x07, 0x36, 0x36, 0x37, 0x37, 0x36, 0x36, 0x37, 0x35, 0x26, 0x26, 0x35, + 0x34, 0x36, 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x23, 0x37, 0x33, 0x32, 0x16, 0x15, 0x14, 0x07, 0x07, 0x06, 0x06, + 0x15, 0x14, 0x33, 0x07, 0x22, 0x06, 0x07, 0x07, 0x06, 0x06, 0x23, 0x23, 0x33, 0x33, 0x2a, 0x09, 0x1d, 0x0c, 0x43, + 0x36, 0x2a, 0x26, 0x04, 0x03, 0x13, 0x02, 0x03, 0x4a, 0x15, 0x15, 0x56, 0x4c, 0x09, 0x14, 0x02, 0x03, 0x61, 0x17, + 0x3b, 0x40, 0x0a, 0x1d, 0x11, 0x58, 0x5d, 0x19, 0x2e, 0x01, 0x1b, 0x29, 0x89, 0x36, 0x36, 0x07, 0x04, 0x0d, 0x37, + 0x2a, 0x0a, 0x19, 0x0b, 0x59, 0x0a, 0x10, 0x07, 0x2d, 0x70, 0x45, 0x38, 0x1d, 0x24, 0x5d, 0x0a, 0x10, 0x07, 0x44, + 0x72, 0x28, 0x30, 0x86, 0x4e, 0x4a, 0x00, 0x01, 0x00, 0x35, 0x01, 0x0d, 0x02, 0x1a, 0x01, 0xb4, 0x00, 0x17, 0x00, + 0x3c, 0xb1, 0x06, 0x64, 0x44, 0x40, 0x31, 0x07, 0x01, 0x02, 0x01, 0x13, 0x01, 0x03, 0x00, 0x02, 0x4c, 0x12, 0x01, + 0x01, 0x4a, 0x06, 0x01, 0x03, 0x49, 0x00, 0x02, 0x00, 0x03, 0x02, 0x59, 0x00, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, + 0x69, 0x00, 0x02, 0x02, 0x03, 0x61, 0x00, 0x03, 0x02, 0x03, 0x51, 0x24, 0x24, 0x24, 0x22, 0x04, 0x0d, 0x1a, 0x2b, + 0xb1, 0x06, 0x00, 0x44, 0x01, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x35, 0x36, 0x33, 0x32, 0x16, 0x17, 0x16, 0x16, + 0x33, 0x32, 0x36, 0x37, 0x15, 0x06, 0x23, 0x22, 0x26, 0x01, 0x16, 0x25, 0x33, 0x17, 0x1c, 0x3d, 0x19, 0x32, 0x4b, + 0x1d, 0x3b, 0x2f, 0x25, 0x34, 0x16, 0x1d, 0x3c, 0x19, 0x32, 0x4b, 0x1d, 0x3b, 0x01, 0x2d, 0x10, 0x0b, 0x22, 0x19, + 0x71, 0x35, 0x0b, 0x14, 0x10, 0x0b, 0x22, 0x19, 0x71, 0x35, 0x0c, 0x00, 0x01, 0x00, 0x38, 0x01, 0x9f, 0x01, 0xa7, + 0x03, 0x55, 0x00, 0x18, 0x00, 0x32, 0x40, 0x2f, 0x0b, 0x01, 0x00, 0x01, 0x0a, 0x01, 0x02, 0x00, 0x02, 0x4c, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x69, 0x00, 0x02, 0x03, 0x03, 0x02, 0x57, 0x00, 0x02, 0x02, 0x03, 0x5f, 0x04, + 0x01, 0x03, 0x02, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x17, 0x24, 0x27, 0x05, 0x0c, 0x19, 0x2b, 0x13, + 0x37, 0x37, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, + 0x06, 0x07, 0x07, 0x33, 0x07, 0x38, 0x11, 0x85, 0x30, 0x32, 0x19, 0x11, 0x2a, 0x32, 0x31, 0x24, 0x51, 0x35, 0x3d, + 0x47, 0x1f, 0x3d, 0x2d, 0x3f, 0xa9, 0x14, 0x01, 0x9f, 0x51, 0x6b, 0x27, 0x31, 0x1c, 0x14, 0x14, 0x28, 0x4d, 0x1c, + 0x1d, 0x3e, 0x2f, 0x29, 0x3b, 0x34, 0x21, 0x2e, 0x62, 0x00, 0x00, 0x01, 0x00, 0x48, 0x01, 0x97, 0x01, 0xa8, 0x03, + 0x54, 0x00, 0x2b, 0x00, 0x4d, 0x40, 0x4a, 0x1a, 0x01, 0x04, 0x05, 0x19, 0x01, 0x03, 0x04, 0x24, 0x01, 0x02, 0x03, + 0x04, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x05, 0x4c, 0x00, 0x05, 0x00, 0x04, 0x03, 0x05, 0x04, 0x69, 0x00, + 0x03, 0x00, 0x02, 0x01, 0x03, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, + 0x01, 0x00, 0x01, 0x00, 0x51, 0x01, 0x00, 0x1e, 0x1c, 0x17, 0x15, 0x11, 0x0f, 0x0e, 0x0c, 0x08, 0x06, 0x00, 0x2b, + 0x01, 0x2b, 0x07, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, + 0x23, 0x23, 0x37, 0x33, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x07, 0x27, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x16, 0x15, 0x14, 0x06, 0x07, 0x15, 0x16, 0x16, 0x15, 0x14, 0x06, 0x06, 0xca, 0x25, 0x45, 0x18, 0x1d, 0x3d, 0x22, + 0x23, 0x32, 0x19, 0x1f, 0x3e, 0x11, 0x2c, 0x29, 0x2f, 0x19, 0x16, 0x16, 0x2f, 0x17, 0x28, 0x23, 0x4a, 0x2c, 0x33, + 0x3c, 0x1b, 0x3e, 0x2c, 0x29, 0x22, 0x37, 0x58, 0x01, 0x97, 0x0f, 0x0c, 0x5e, 0x10, 0x13, 0x1d, 0x1d, 0x12, 0x19, + 0x4e, 0x1b, 0x1c, 0x14, 0x13, 0x11, 0x0f, 0x49, 0x17, 0x16, 0x1d, 0x2f, 0x1b, 0x33, 0x33, 0x0b, 0x04, 0x09, 0x2c, + 0x20, 0x31, 0x3e, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x5b, 0x01, 0x9f, 0x01, 0x83, 0x03, 0x4b, 0x00, 0x0c, 0x00, 0x20, + 0x40, 0x1d, 0x08, 0x07, 0x03, 0x03, 0x01, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x01, 0x01, 0x00, 0x57, 0x00, 0x00, 0x00, + 0x01, 0x5f, 0x00, 0x01, 0x00, 0x01, 0x4f, 0x11, 0x19, 0x02, 0x0c, 0x18, 0x2b, 0x13, 0x36, 0x36, 0x37, 0x06, 0x06, + 0x07, 0x07, 0x27, 0x37, 0x33, 0x03, 0x23, 0xd9, 0x07, 0x0f, 0x05, 0x09, 0x17, 0x07, 0x40, 0x32, 0xc3, 0x65, 0x5b, + 0x78, 0x02, 0x61, 0x1f, 0x35, 0x11, 0x07, 0x11, 0x05, 0x28, 0x51, 0x79, 0xfe, 0x54, 0x00, 0x00, 0x01, 0xfe, 0xfb, + 0x00, 0x00, 0x01, 0x83, 0x02, 0xca, 0x00, 0x03, 0x00, 0x19, 0x40, 0x16, 0x00, 0x00, 0x00, 0x6a, 0x4d, 0x02, 0x01, + 0x01, 0x01, 0x6b, 0x01, 0x4e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x11, 0x03, 0x0d, 0x17, 0x2b, 0x21, 0x01, 0x33, + 0x01, 0xfe, 0xfb, 0x02, 0x13, 0x75, 0xfd, 0xef, 0x02, 0xca, 0xfd, 0x36, 0x00, 0x02, 0x00, 0x32, 0x01, 0x9f, 0x01, + 0xa8, 0x03, 0x4e, 0x00, 0x0a, 0x00, 0x13, 0x00, 0x61, 0xb5, 0x10, 0x01, 0x02, 0x01, 0x01, 0x4c, 0x4b, 0xb0, 0x11, + 0x50, 0x58, 0x40, 0x1f, 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x00, 0x04, 0x71, 0x05, 0x01, 0x02, + 0x00, 0x00, 0x02, 0x57, 0x05, 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x1b, 0x40, 0x1e, + 0x00, 0x01, 0x02, 0x01, 0x85, 0x06, 0x01, 0x04, 0x00, 0x04, 0x86, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x57, 0x05, + 0x01, 0x02, 0x02, 0x00, 0x60, 0x03, 0x01, 0x00, 0x02, 0x00, 0x50, 0x59, 0x40, 0x0f, 0x00, 0x00, 0x0c, 0x0b, 0x00, + 0x0a, 0x00, 0x0a, 0x11, 0x11, 0x12, 0x11, 0x07, 0x0c, 0x1a, 0x2b, 0x13, 0x37, 0x23, 0x37, 0x13, 0x33, 0x03, 0x33, + 0x07, 0x23, 0x07, 0x27, 0x33, 0x37, 0x36, 0x36, 0x37, 0x06, 0x06, 0x07, 0xd8, 0x10, 0xb6, 0x0f, 0xe8, 0x7f, 0x3b, + 0x3a, 0x11, 0x3a, 0x10, 0xa8, 0x55, 0x14, 0x05, 0x07, 0x07, 0x09, 0x19, 0x08, 0x01, 0x9f, 0x4a, 0x55, 0x01, 0x10, + 0xfe, 0xed, 0x52, 0x4a, 0x9c, 0x50, 0x14, 0x19, 0x18, 0x0d, 0x1f, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x49, 0x01, 0x97, + 0x01, 0xac, 0x03, 0x4b, 0x00, 0x1e, 0x00, 0x47, 0x40, 0x44, 0x15, 0x10, 0x02, 0x02, 0x05, 0x0f, 0x04, 0x02, 0x01, + 0x02, 0x03, 0x01, 0x00, 0x01, 0x03, 0x4c, 0x00, 0x03, 0x00, 0x04, 0x05, 0x03, 0x04, 0x67, 0x00, 0x05, 0x00, 0x02, + 0x01, 0x05, 0x02, 0x69, 0x00, 0x01, 0x00, 0x00, 0x01, 0x59, 0x00, 0x01, 0x01, 0x00, 0x61, 0x06, 0x01, 0x00, 0x01, + 0x00, 0x51, 0x01, 0x00, 0x19, 0x17, 0x14, 0x13, 0x12, 0x11, 0x0d, 0x0b, 0x08, 0x06, 0x00, 0x1e, 0x01, 0x1e, 0x07, + 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x35, 0x34, 0x23, 0x22, 0x06, 0x07, + 0x27, 0x37, 0x21, 0x07, 0x23, 0x07, 0x36, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0xc5, 0x22, 0x43, 0x17, + 0x19, 0x3c, 0x1c, 0x32, 0x2a, 0x40, 0x10, 0x23, 0x0e, 0x25, 0x3a, 0x01, 0x02, 0x14, 0xad, 0x15, 0x08, 0x19, 0x13, + 0x38, 0x45, 0x33, 0x58, 0x01, 0x97, 0x0d, 0x0d, 0x59, 0x0f, 0x11, 0x2b, 0x1d, 0x36, 0x06, 0x04, 0x21, 0xcc, 0x5a, + 0x44, 0x02, 0x04, 0x40, 0x35, 0x35, 0x4b, 0x27, 0x00, 0x01, 0x00, 0x62, 0x01, 0x9f, 0x01, 0xd2, 0x03, 0x4b, 0x00, + 0x06, 0x00, 0x24, 0x40, 0x21, 0x03, 0x01, 0x02, 0x00, 0x02, 0x86, 0x00, 0x01, 0x00, 0x00, 0x01, 0x57, 0x00, 0x01, + 0x01, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x11, 0x11, 0x04, 0x0c, 0x18, + 0x2b, 0x13, 0x13, 0x23, 0x37, 0x21, 0x07, 0x03, 0x62, 0xe2, 0xc6, 0x13, 0x01, 0x41, 0x0f, 0xe3, 0x01, 0x9f, 0x01, + 0x52, 0x5a, 0x49, 0xfe, 0x9d, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x01, 0x95, 0x01, 0xae, 0x03, 0x55, 0x00, 0x18, 0x00, + 0x24, 0x00, 0x30, 0x00, 0x39, 0x40, 0x36, 0x2b, 0x13, 0x06, 0x03, 0x03, 0x02, 0x01, 0x4c, 0x00, 0x01, 0x00, 0x02, + 0x03, 0x01, 0x02, 0x69, 0x05, 0x01, 0x03, 0x00, 0x00, 0x03, 0x59, 0x05, 0x01, 0x03, 0x03, 0x00, 0x61, 0x04, 0x01, + 0x00, 0x03, 0x00, 0x51, 0x26, 0x25, 0x01, 0x00, 0x25, 0x30, 0x26, 0x30, 0x20, 0x1e, 0x0e, 0x0c, 0x00, 0x18, 0x01, + 0x18, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x36, 0x37, 0x26, 0x26, 0x35, 0x34, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x15, 0x14, 0x06, 0x07, 0x16, 0x16, 0x15, 0x14, 0x06, 0x03, 0x36, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, + 0x06, 0x15, 0x14, 0x16, 0x07, 0x32, 0x36, 0x35, 0x34, 0x26, 0x27, 0x06, 0x06, 0x15, 0x14, 0x16, 0xe4, 0x49, 0x4f, + 0x3b, 0x35, 0x19, 0x1c, 0x2b, 0x46, 0x28, 0x48, 0x46, 0x30, 0x2c, 0x20, 0x26, 0x66, 0x1d, 0x14, 0x1a, 0x10, 0x14, + 0x11, 0x18, 0x12, 0x1c, 0x1a, 0x1d, 0x15, 0x13, 0x16, 0x28, 0x1a, 0x01, 0x95, 0x42, 0x30, 0x2e, 0x3b, 0x12, 0x11, + 0x2b, 0x1e, 0x27, 0x36, 0x1c, 0x3a, 0x2c, 0x2b, 0x33, 0x10, 0x11, 0x30, 0x24, 0x43, 0x44, 0x01, 0x17, 0x09, 0x1a, + 0x16, 0x0d, 0x16, 0x18, 0x14, 0x10, 0x18, 0xd2, 0x1f, 0x15, 0x15, 0x1c, 0x0b, 0x07, 0x21, 0x1b, 0x14, 0x19, 0x00, + 0x02, 0x00, 0x5d, 0x01, 0x95, 0x01, 0xb6, 0x03, 0x55, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x31, 0x40, 0x2e, 0x00, 0x01, + 0x00, 0x03, 0x02, 0x01, 0x03, 0x69, 0x05, 0x01, 0x02, 0x00, 0x00, 0x02, 0x59, 0x05, 0x01, 0x02, 0x02, 0x00, 0x61, + 0x04, 0x01, 0x00, 0x02, 0x00, 0x51, 0x10, 0x0f, 0x01, 0x00, 0x17, 0x15, 0x0f, 0x1c, 0x10, 0x1c, 0x09, 0x07, 0x00, + 0x0e, 0x01, 0x0e, 0x06, 0x0c, 0x16, 0x2b, 0x13, 0x22, 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x15, 0x14, + 0x06, 0x06, 0x27, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0xe7, 0x40, 0x4a, 0x13, 0x2f, + 0x4f, 0x3c, 0x43, 0x49, 0x30, 0x5c, 0x3a, 0x12, 0x1d, 0x14, 0x0b, 0x1c, 0x10, 0x1d, 0x14, 0x0c, 0x01, 0x95, 0x4d, + 0x46, 0x30, 0x68, 0x5c, 0x39, 0x4d, 0x4a, 0x52, 0x87, 0x50, 0x65, 0x27, 0x3c, 0x45, 0x1e, 0x2f, 0x24, 0x3c, 0x45, + 0x21, 0x2f, 0x00, 0x02, 0x00, 0x5b, 0x01, 0x97, 0x01, 0xb7, 0x03, 0x54, 0x00, 0x1d, 0x00, 0x2a, 0x00, 0x4b, 0x40, + 0x48, 0x0b, 0x01, 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x13, 0x01, 0x05, 0x03, 0x03, 0x4c, 0x00, 0x01, 0x00, 0x02, + 0x03, 0x01, 0x02, 0x69, 0x00, 0x03, 0x00, 0x05, 0x04, 0x03, 0x05, 0x69, 0x07, 0x01, 0x04, 0x00, 0x00, 0x04, 0x59, + 0x07, 0x01, 0x04, 0x04, 0x00, 0x61, 0x06, 0x01, 0x00, 0x04, 0x00, 0x51, 0x1f, 0x1e, 0x01, 0x00, 0x25, 0x23, 0x1e, + 0x2a, 0x1f, 0x2a, 0x18, 0x16, 0x10, 0x0e, 0x09, 0x07, 0x00, 0x1d, 0x01, 0x1d, 0x08, 0x0c, 0x16, 0x2b, 0x13, 0x22, + 0x26, 0x35, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x06, 0x07, 0x33, 0x36, + 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x27, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x06, 0x15, + 0x14, 0x16, 0xf0, 0x43, 0x52, 0x16, 0x39, 0x66, 0x4f, 0x14, 0x39, 0x0b, 0x15, 0x0a, 0x29, 0x1c, 0x2d, 0x36, 0x1b, + 0x07, 0x04, 0x0e, 0x30, 0x21, 0x37, 0x37, 0x2b, 0x4e, 0x34, 0x20, 0x22, 0x19, 0x14, 0x19, 0x1c, 0x0c, 0x16, 0x01, + 0x97, 0x57, 0x55, 0x26, 0x5e, 0x56, 0x37, 0x06, 0x04, 0x5c, 0x05, 0x09, 0x23, 0x34, 0x1a, 0x11, 0x1a, 0x40, 0x32, + 0x31, 0x4f, 0x2d, 0x55, 0x2f, 0x1f, 0x17, 0x1b, 0x1b, 0x23, 0x0d, 0x17, 0x1e, 0x00, 0x00, 0x02, 0x00, 0x5b, 0x01, + 0x97, 0x01, 0xb1, 0x03, 0x54, 0x00, 0x1c, 0x00, 0x28, 0x00, 0x4a, 0x40, 0x47, 0x12, 0x01, 0x03, 0x04, 0x0b, 0x01, + 0x02, 0x03, 0x0a, 0x01, 0x01, 0x02, 0x03, 0x4c, 0x06, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x69, 0x07, 0x01, + 0x04, 0x00, 0x03, 0x02, 0x04, 0x03, 0x69, 0x00, 0x02, 0x01, 0x01, 0x02, 0x59, 0x00, 0x02, 0x02, 0x01, 0x61, 0x00, + 0x01, 0x02, 0x01, 0x51, 0x1e, 0x1d, 0x01, 0x00, 0x24, 0x22, 0x1d, 0x28, 0x1e, 0x28, 0x17, 0x15, 0x0f, 0x0d, 0x08, + 0x06, 0x00, 0x1c, 0x01, 0x1c, 0x08, 0x0c, 0x16, 0x2b, 0x01, 0x32, 0x16, 0x15, 0x14, 0x06, 0x06, 0x23, 0x22, 0x26, + 0x27, 0x35, 0x16, 0x16, 0x33, 0x32, 0x36, 0x36, 0x37, 0x23, 0x06, 0x06, 0x23, 0x22, 0x26, 0x35, 0x34, 0x36, 0x36, + 0x17, 0x32, 0x36, 0x35, 0x34, 0x26, 0x23, 0x22, 0x06, 0x15, 0x14, 0x16, 0x01, 0x1c, 0x4b, 0x4a, 0x40, 0x79, 0x56, + 0x13, 0x29, 0x0b, 0x0d, 0x2d, 0x10, 0x31, 0x3c, 0x23, 0x09, 0x03, 0x10, 0x2f, 0x21, 0x37, 0x37, 0x2b, 0x4f, 0x1f, + 0x1f, 0x22, 0x16, 0x17, 0x1e, 0x23, 0x19, 0x03, 0x54, 0x52, 0x46, 0x58, 0x84, 0x49, 0x05, 0x04, 0x5b, 0x05, 0x07, + 0x1e, 0x33, 0x1d, 0x10, 0x18, 0x41, 0x31, 0x32, 0x4e, 0x2d, 0xd3, 0x2b, 0x1f, 0x17, 0x1e, 0x2d, 0x20, 0x17, 0x1b, + 0x00, 0x00, 0x01, 0x00, 0x2a, 0x00, 0x00, 0x01, 0xe5, 0x02, 0xfd, 0x00, 0x17, 0x00, 0x35, 0x40, 0x32, 0x0b, 0x01, + 0x02, 0x01, 0x0c, 0x01, 0x03, 0x02, 0x02, 0x4c, 0x00, 0x01, 0x00, 0x02, 0x03, 0x01, 0x02, 0x69, 0x04, 0x01, 0x00, + 0x00, 0x03, 0x5f, 0x00, 0x03, 0x03, 0x28, 0x4d, 0x06, 0x01, 0x05, 0x05, 0x27, 0x05, 0x4e, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x17, 0x11, 0x13, 0x25, 0x25, 0x11, 0x07, 0x07, 0x1b, 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, + 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x2a, 0x5b, 0x55, 0x0f, + 0x5f, 0x0a, 0x15, 0x5f, 0x50, 0x22, 0x41, 0x16, 0x26, 0x0e, 0x22, 0x11, 0x19, 0x21, 0x07, 0x0a, 0x6c, 0x19, 0x6b, + 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x61, 0x51, 0x0e, 0x0a, 0x69, 0x06, 0x08, 0x1c, 0x22, 0x2a, 0x70, 0xfe, 0x4e, + 0x00, 0x01, 0xff, 0x95, 0xff, 0x10, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x41, 0x00, 0xc5, 0x40, 0x16, 0x23, 0x13, 0x02, + 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x02, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, + 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, + 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x27, 0x07, 0x01, 0x04, + 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, + 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x40, + 0x27, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, + 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0d, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x59, 0x59, 0x40, 0x21, 0x01, 0x00, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, + 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x0e, 0x0d, + 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, + 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, + 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, + 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, + 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, + 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, + 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0xf0, 0x0c, 0x76, 0x0a, + 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, + 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, + 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x00, 0x03, 0xff, 0x95, 0xff, 0x10, 0x03, 0xfe, 0x02, 0xfd, 0x00, + 0x41, 0x00, 0x4d, 0x00, 0x51, 0x01, 0x75, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x03, + 0x24, 0x14, 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x1b, 0x40, + 0x16, 0x23, 0x13, 0x02, 0x04, 0x0e, 0x24, 0x14, 0x02, 0x0d, 0x04, 0x36, 0x03, 0x02, 0x01, 0x10, 0x35, 0x02, 0x02, + 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, + 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, + 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, + 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x12, 0x01, + 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, + 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, + 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x3c, 0x07, 0x01, 0x04, 0x04, + 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x03, 0x61, 0x0e, 0x06, 0x02, 0x03, + 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, 0x4d, 0x13, 0x01, + 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x40, 0x39, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, 0x12, 0x01, 0x0d, 0x0d, 0x0e, + 0x61, 0x00, 0x0e, 0x0e, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x0f, 0x08, 0x02, 0x05, 0x05, 0x6d, + 0x4d, 0x13, 0x01, 0x10, 0x10, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x11, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x31, 0x4e, 0x4e, 0x43, 0x42, 0x01, 0x00, 0x4e, 0x51, 0x4e, 0x51, 0x50, 0x4f, + 0x49, 0x47, 0x42, 0x4d, 0x43, 0x4d, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, 0x2b, 0x28, 0x26, 0x21, + 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, 0x14, 0x0d, 0x16, 0x2b, + 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, + 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, + 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, + 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x01, 0x22, 0x26, 0x35, 0x34, 0x36, 0x33, 0x32, 0x16, 0x15, 0x14, 0x06, 0x01, + 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, + 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, + 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, + 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, 0x2e, 0x4f, 0x03, 0x7e, 0x1f, 0x2b, 0x2f, 0x2a, 0x1d, 0x2c, 0x2b, + 0xfe, 0xfe, 0x74, 0x93, 0x74, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, 0x4f, 0x0d, + 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x70, + 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x03, 0x56, + 0x1b, 0x21, 0x2a, 0x2c, 0x1a, 0x21, 0x27, 0x30, 0xfd, 0x9a, 0x02, 0x22, 0xfd, 0xde, 0x00, 0x02, 0xff, 0x95, 0xff, + 0x10, 0x04, 0x05, 0x02, 0xfd, 0x00, 0x41, 0x00, 0x45, 0x01, 0x3c, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x16, 0x23, + 0x13, 0x02, 0x04, 0x03, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, + 0x04, 0x4c, 0x1b, 0x40, 0x16, 0x23, 0x13, 0x02, 0x04, 0x0d, 0x24, 0x14, 0x02, 0x05, 0x04, 0x36, 0x03, 0x02, 0x01, + 0x0e, 0x35, 0x02, 0x02, 0x00, 0x01, 0x04, 0x4c, 0x59, 0x4b, 0xb0, 0x0a, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, + 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, + 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, + 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x0c, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, + 0x0d, 0x06, 0x02, 0x03, 0x03, 0x6c, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, + 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, + 0x00, 0x4e, 0x1b, 0x4b, 0xb0, 0x2e, 0x50, 0x58, 0x40, 0x2e, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x0d, 0x06, 0x02, + 0x03, 0x03, 0x72, 0x4d, 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, + 0x0e, 0x0e, 0x6b, 0x4d, 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x1b, + 0x40, 0x32, 0x00, 0x0d, 0x0d, 0x6c, 0x4d, 0x07, 0x01, 0x04, 0x04, 0x03, 0x61, 0x06, 0x01, 0x03, 0x03, 0x72, 0x4d, + 0x0c, 0x09, 0x02, 0x02, 0x02, 0x05, 0x5f, 0x08, 0x01, 0x05, 0x05, 0x6d, 0x4d, 0x10, 0x01, 0x0e, 0x0e, 0x6b, 0x4d, + 0x0b, 0x01, 0x01, 0x01, 0x00, 0x61, 0x0a, 0x0f, 0x02, 0x00, 0x00, 0x6f, 0x00, 0x4e, 0x59, 0x59, 0x59, 0x40, 0x29, + 0x42, 0x42, 0x01, 0x00, 0x42, 0x45, 0x42, 0x45, 0x44, 0x43, 0x3d, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2e, 0x2d, 0x2c, + 0x2b, 0x28, 0x26, 0x21, 0x1f, 0x1c, 0x1b, 0x18, 0x16, 0x11, 0x0f, 0x0a, 0x09, 0x06, 0x04, 0x00, 0x41, 0x01, 0x41, + 0x11, 0x0d, 0x16, 0x2b, 0x07, 0x22, 0x27, 0x35, 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, + 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, + 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, 0x23, 0x03, 0x0e, 0x02, 0x23, 0x22, 0x27, 0x35, + 0x16, 0x33, 0x32, 0x36, 0x37, 0x13, 0x23, 0x03, 0x0e, 0x02, 0x25, 0x13, 0x33, 0x03, 0x16, 0x33, 0x22, 0x1e, 0x1a, + 0x1e, 0x2d, 0x09, 0x64, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, + 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, + 0x6b, 0x18, 0x6b, 0x69, 0x0a, 0x2e, 0x4f, 0x3e, 0x33, 0x22, 0x1e, 0x1a, 0x1e, 0x2d, 0x09, 0x64, 0xc1, 0x69, 0x0a, + 0x2e, 0x4f, 0x02, 0xa9, 0xa1, 0x93, 0xa1, 0xf0, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0x47, 0x29, 0x29, 0x63, + 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, + 0x1e, 0x70, 0xfe, 0x13, 0x32, 0x52, 0x31, 0x0c, 0x76, 0x0a, 0x28, 0x2b, 0x01, 0xd7, 0xfe, 0x13, 0x32, 0x52, 0x31, + 0xf0, 0x02, 0xf8, 0xfd, 0x08, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, + 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0xff, 0x96, 0xff, 0x10, 0x02, 0xbd, + 0x02, 0xfd, 0x00, 0x26, 0x00, 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x29, 0x00, 0x00, 0x03, 0x36, 0x02, 0xfd, 0x00, 0x2b, 0x00, 0x42, 0x40, 0x3f, 0x1b, 0x0b, 0x02, 0x02, 0x01, 0x1c, + 0x0c, 0x02, 0x03, 0x02, 0x02, 0x4c, 0x04, 0x01, 0x01, 0x05, 0x01, 0x02, 0x03, 0x01, 0x02, 0x69, 0x09, 0x07, 0x02, + 0x00, 0x00, 0x03, 0x5f, 0x06, 0x01, 0x03, 0x03, 0x28, 0x4d, 0x0b, 0x0a, 0x02, 0x08, 0x08, 0x27, 0x08, 0x4e, 0x00, + 0x00, 0x00, 0x2b, 0x00, 0x2b, 0x2a, 0x29, 0x11, 0x11, 0x13, 0x25, 0x23, 0x13, 0x25, 0x25, 0x11, 0x0c, 0x07, 0x1f, + 0x2b, 0x33, 0x13, 0x23, 0x3f, 0x02, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, + 0x07, 0x33, 0x37, 0x36, 0x36, 0x33, 0x32, 0x16, 0x17, 0x07, 0x26, 0x26, 0x23, 0x22, 0x06, 0x07, 0x07, 0x33, 0x07, + 0x23, 0x03, 0x23, 0x13, 0x23, 0x03, 0x29, 0x5c, 0x50, 0x0f, 0x59, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, + 0x0e, 0x1f, 0x14, 0x1c, 0x22, 0x06, 0x06, 0xc1, 0x09, 0x16, 0x63, 0x50, 0x22, 0x39, 0x18, 0x27, 0x0e, 0x1f, 0x14, + 0x1c, 0x22, 0x06, 0x06, 0x6b, 0x18, 0x6b, 0x5c, 0x93, 0x5c, 0xc1, 0x5c, 0x01, 0xb2, 0x47, 0x29, 0x29, 0x63, 0x4f, + 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, 0x29, 0x63, 0x4f, 0x0d, 0x0b, 0x6d, 0x06, 0x09, 0x27, 0x20, 0x1e, + 0x70, 0xfe, 0x4e, 0x01, 0xb2, 0xfe, 0x4e, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, 0x0a, 0x02, 0xfd, 0x00, 0x26, + 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, 0x00, 0x29, 0x00, 0x00, 0x04, + 0x11, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x71, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4d, 0x02, 0xc9, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x2a, 0x00, 0x00, 0x02, 0xb6, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x4a, 0x01, + 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x2a, 0x00, 0x00, 0x02, 0xbd, 0x02, 0xfd, 0x00, 0x26, 0x00, 0x6b, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x4d, 0x01, 0x75, 0x00, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf5, 0x01, 0x5c, 0x01, 0xb5, 0x01, + 0x07, 0x00, 0x68, 0xff, 0xa6, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, + 0xff, 0xff, 0x00, 0x0e, 0xff, 0xff, 0x01, 0x36, 0x01, 0xab, 0x01, 0x07, 0x00, 0x62, 0xff, 0xb3, 0xfe, 0x60, 0x00, + 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x01, 0x51, + 0x01, 0xb5, 0x01, 0x07, 0x00, 0x60, 0xff, 0xaa, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, + 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf7, 0x01, 0x58, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x61, 0xff, 0xb0, + 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xe1, 0xff, + 0xff, 0x01, 0x57, 0x01, 0xae, 0x01, 0x07, 0x00, 0x64, 0xff, 0xaf, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, + 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xf7, 0x01, 0x5e, 0x01, 0xab, 0x01, 0x07, 0x00, + 0x65, 0xff, 0xb2, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, + 0x00, 0x04, 0xff, 0xf7, 0x01, 0x60, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x69, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, + 0x00, 0x02, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x0b, 0xff, 0xff, 0x01, 0x7b, 0x01, 0xab, + 0x01, 0x07, 0x00, 0x66, 0xff, 0xa9, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, + 0x00, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xf5, 0x01, 0x58, 0x01, 0xb5, 0x01, 0x07, 0x00, 0x67, 0xff, 0xaa, 0xfe, 0x60, + 0x00, 0x09, 0xb1, 0x00, 0x03, 0xb8, 0xfe, 0x60, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x03, 0xff, 0xf7, 0x01, + 0x59, 0x01, 0xb4, 0x01, 0x07, 0x00, 0x6a, 0xff, 0xa8, 0xfe, 0x60, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xfe, 0x60, + 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x3f, 0x01, 0x13, 0x01, 0x98, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x68, 0xff, + 0xe2, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x47, + 0x01, 0x1d, 0x01, 0x6f, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x62, 0xff, 0xec, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, + 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1b, 0x01, 0x1d, 0x01, 0x8a, 0x02, 0xd3, 0x01, 0x07, + 0x00, 0x60, 0xff, 0xe3, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, + 0xff, 0x00, 0x2f, 0x01, 0x15, 0x01, 0x8f, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x61, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, + 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x1c, 0x01, 0x1d, 0x01, 0x92, 0x02, + 0xcc, 0x01, 0x07, 0x00, 0x64, 0xff, 0xea, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, + 0x2b, 0x00, 0xff, 0xff, 0x00, 0x37, 0x01, 0x15, 0x01, 0x9a, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x65, 0xff, 0xee, 0xff, + 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x44, 0x01, 0x15, + 0x01, 0xa0, 0x02, 0xd2, 0x01, 0x07, 0x00, 0x69, 0xff, 0xe9, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, + 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x4d, 0x01, 0x1d, 0x01, 0xbd, 0x02, 0xc9, 0x01, 0x07, 0x00, 0x66, + 0xff, 0xeb, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x01, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, + 0x33, 0x01, 0x13, 0x01, 0x95, 0x02, 0xd3, 0x01, 0x07, 0x00, 0x67, 0xff, 0xe7, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, + 0x03, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, 0xff, 0xff, 0x00, 0x41, 0x01, 0x15, 0x01, 0x97, 0x02, 0xd2, 0x01, + 0x07, 0x00, 0x6a, 0xff, 0xe6, 0xff, 0x7e, 0x00, 0x09, 0xb1, 0x00, 0x02, 0xb8, 0xff, 0x7e, 0xb0, 0x35, 0x2b, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8a, 0x00, 0xd3, 0x00, 0x18, 0x00, 0x66, 0x00, 0x06, 0x00, 0x02, 0x00, + 0x98, 0x00, 0xfc, 0x00, 0x8d, 0x00, 0x00, 0x01, 0x89, 0x0e, 0x0c, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x33, 0x00, 0x5b, 0x00, 0xaf, 0x01, 0x36, 0x01, 0xfc, 0x02, 0x9b, 0x02, 0xb6, 0x02, 0xde, 0x03, + 0x10, 0x03, 0x3d, 0x03, 0x65, 0x03, 0x88, 0x03, 0xa4, 0x03, 0xc7, 0x03, 0xe2, 0x04, 0x2a, 0x04, 0x53, 0x04, 0x98, + 0x04, 0xfc, 0x05, 0x3b, 0x05, 0x91, 0x05, 0xfc, 0x06, 0x1f, 0x06, 0x88, 0x06, 0xf6, 0x07, 0x33, 0x07, 0x6d, 0x07, + 0x83, 0x07, 0xae, 0x07, 0xc4, 0x08, 0x20, 0x08, 0xd7, 0x09, 0x0f, 0x09, 0x65, 0x09, 0xae, 0x09, 0xe6, 0x0a, 0x15, + 0x0a, 0x3f, 0x0a, 0x92, 0x0a, 0xbf, 0x0a, 0xea, 0x0b, 0x1c, 0x0b, 0x4a, 0x0b, 0x69, 0x0b, 0xa8, 0x0b, 0xde, 0x0c, + 0x24, 0x0c, 0x5f, 0x0c, 0xad, 0x0c, 0xf0, 0x0d, 0x46, 0x0d, 0x69, 0x0d, 0xa4, 0x0d, 0xd1, 0x0e, 0x20, 0x0e, 0x4e, + 0x0e, 0x76, 0x0e, 0xa0, 0x0e, 0xc4, 0x0e, 0xde, 0x0f, 0x02, 0x0f, 0x29, 0x0f, 0x49, 0x0f, 0x75, 0x0f, 0xec, 0x10, + 0x6a, 0x10, 0xb4, 0x11, 0x31, 0x11, 0x8a, 0x12, 0x14, 0x12, 0xac, 0x12, 0xf0, 0x13, 0x25, 0x13, 0x72, 0x13, 0xa5, + 0x13, 0xbf, 0x14, 0x2a, 0x14, 0x78, 0x14, 0xbd, 0x15, 0x2f, 0x15, 0xa9, 0x15, 0xfe, 0x16, 0x53, 0x16, 0xb2, 0x17, + 0x0b, 0x17, 0x38, 0x17, 0x87, 0x17, 0xb3, 0x17, 0xf9, 0x18, 0x22, 0x18, 0x80, 0x18, 0xa5, 0x18, 0xfd, 0x19, 0x42, + 0x19, 0x84, 0x19, 0xea, 0x1a, 0x15, 0x1a, 0x30, 0x1a, 0x86, 0x1a, 0xd9, 0x1a, 0xfe, 0x1b, 0x63, 0x1b, 0xa7, 0x1c, + 0x0c, 0x1c, 0x6e, 0x1c, 0xb0, 0x1d, 0x72, 0x1e, 0xa5, 0x1f, 0xab, 0x1f, 0xb7, 0x1f, 0xc3, 0x20, 0x27, 0x20, 0x33, + 0x20, 0x3f, 0x20, 0x4b, 0x20, 0x57, 0x20, 0x66, 0x20, 0x75, 0x20, 0x84, 0x20, 0x93, 0x20, 0xa2, 0x20, 0xb1, 0x20, + 0xc0, 0x20, 0xcf, 0x20, 0xde, 0x20, 0xed, 0x20, 0xfc, 0x21, 0x0b, 0x21, 0x1a, 0x21, 0x29, 0x21, 0x38, 0x21, 0x47, + 0x21, 0x56, 0x21, 0x65, 0x21, 0x74, 0x21, 0x83, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xd7, 0xbc, + 0xcf, 0x60, 0xc2, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x07, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x80, 0xcc, 0xa2, + 0x00, 0x00, 0x00, 0x00, 0xe3, 0x63, 0xc4, 0x58, 0xfd, 0x5c, 0xfe, 0x7b, 0x0a, 0xdc, 0x04, 0x26, 0x00, 0x03, 0x00, + 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x00, 0x5f, 0x01, 0x04, 0x00, 0x00, 0x01, 0x1f, + 0x00, 0x0b, 0x01, 0xc5, 0x00, 0x62, 0x02, 0x86, 0x00, 0x14, 0x02, 0x27, 0x00, 0x19, 0x03, 0x58, 0x00, 0x38, 0x02, + 0xc4, 0x00, 0x21, 0x00, 0xff, 0x00, 0x62, 0x01, 0x53, 0x00, 0x24, 0x01, 0x55, 0xff, 0xba, 0x02, 0x22, 0x00, 0x55, + 0x02, 0x3c, 0x00, 0x35, 0x01, 0x1f, 0xff, 0xd0, 0x01, 0x43, 0x00, 0x11, 0x01, 0x1f, 0x00, 0x08, 0x01, 0xa8, 0xff, + 0xd3, 0x02, 0x27, 0x00, 0x20, 0x02, 0x27, 0x00, 0x59, 0x02, 0x27, 0xff, 0xe8, 0x02, 0x27, 0x00, 0x07, 0x02, 0x27, + 0xff, 0xf4, 0x02, 0x27, 0x00, 0x0d, 0x02, 0x27, 0x00, 0x2b, 0x02, 0x27, 0x00, 0x26, 0x02, 0x27, 0x00, 0x1b, 0x02, + 0x27, 0x00, 0x2a, 0x01, 0x1f, 0x00, 0x08, 0x01, 0x1f, 0xff, 0xca, 0x02, 0x3c, 0x00, 0x35, 0x02, 0x3c, 0x00, 0x35, + 0x02, 0x3c, 0x00, 0x35, 0x01, 0xcb, 0x00, 0x4d, 0x03, 0x58, 0x00, 0x2d, 0x02, 0x74, 0xff, 0xc4, 0x02, 0x6c, 0x00, + 0x1a, 0x02, 0x65, 0x00, 0x3b, 0x02, 0xa5, 0x00, 0x1a, 0x02, 0x1f, 0x00, 0x1a, 0x02, 0x15, 0x00, 0x1a, 0x02, 0xb2, + 0x00, 0x3b, 0x02, 0xbd, 0x00, 0x1a, 0x01, 0x7f, 0xff, 0xe3, 0x01, 0x4e, 0xff, 0x62, 0x02, 0x65, 0x00, 0x1a, 0x02, + 0x06, 0x00, 0x1a, 0x03, 0x70, 0x00, 0x1a, 0x02, 0xf6, 0x00, 0x19, 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x62, 0x00, 0x1a, + 0x02, 0xdb, 0x00, 0x3b, 0x02, 0x6c, 0x00, 0x1a, 0x02, 0x12, 0x00, 0x14, 0x02, 0x14, 0x00, 0x51, 0x02, 0xb4, 0x00, + 0x44, 0x02, 0x4e, 0x00, 0x5a, 0x03, 0x7e, 0x00, 0x5a, 0x02, 0x62, 0xff, 0xc7, 0x02, 0x34, 0x00, 0x5b, 0x02, 0x18, + 0xff, 0xe2, 0x01, 0x4b, 0xff, 0xee, 0x01, 0xa8, 0x00, 0x6c, 0x01, 0x4b, 0xff, 0xbd, 0x02, 0x27, 0x00, 0x11, 0x01, + 0x90, 0xff, 0xa5, 0x01, 0x44, 0x00, 0x91, 0x02, 0x50, 0x00, 0x2c, 0x02, 0x53, 0x00, 0x12, 0x01, 0xe4, 0x00, 0x2c, + 0x02, 0x52, 0x00, 0x2c, 0x02, 0x2d, 0x00, 0x2c, 0x01, 0x76, 0xff, 0x96, 0x02, 0x54, 0x00, 0x12, 0x02, 0x5c, 0x00, + 0x12, 0x01, 0x2b, 0x00, 0x12, 0x01, 0x2b, 0xff, 0x80, 0x02, 0x38, 0x00, 0x12, 0x01, 0x2b, 0x00, 0x11, 0x03, 0x89, + 0x00, 0x12, 0x02, 0x5c, 0x00, 0x12, 0x02, 0x49, 0x00, 0x2c, 0x02, 0x53, 0xff, 0xdf, 0x02, 0x52, 0x00, 0x2c, 0x01, + 0xa6, 0x00, 0x12, 0x01, 0xdb, 0x00, 0x0b, 0x01, 0x9a, 0x00, 0x2e, 0x02, 0x5c, 0x00, 0x36, 0x02, 0x00, 0x00, 0x32, + 0x03, 0x14, 0x00, 0x3d, 0x02, 0x16, 0xff, 0xce, 0x02, 0x07, 0xff, 0xbb, 0x01, 0xd5, 0xff, 0xee, 0x01, 0x63, 0xff, + 0xff, 0x02, 0x27, 0x00, 0xde, 0x01, 0x63, 0xff, 0xcd, 0x02, 0x3c, 0x00, 0x35, 0x01, 0x7b, 0x00, 0x38, 0x01, 0x7b, + 0x00, 0x48, 0x01, 0x7b, 0x00, 0x5b, 0x00, 0x7d, 0xfe, 0xfb, 0x01, 0x7b, 0x00, 0x32, 0x01, 0x7b, 0x00, 0x49, 0x01, + 0x7b, 0x00, 0x62, 0x01, 0x7b, 0x00, 0x4c, 0x01, 0x7b, 0x00, 0x5d, 0x01, 0x7b, 0x00, 0x5b, 0x01, 0x7b, 0x00, 0x5b, + 0x01, 0x76, 0x00, 0x2a, 0x02, 0xc9, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, 0x03, 0xe8, 0xff, 0x95, 0x02, 0x9e, 0xff, + 0x96, 0x02, 0x9e, 0xff, 0x96, 0x02, 0xc9, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x03, 0xf2, 0x00, 0x29, 0x02, 0x9e, + 0x00, 0x2a, 0x02, 0x9e, 0x00, 0x2a, 0x01, 0x7b, 0x00, 0x03, 0x00, 0x0e, 0xff, 0xe2, 0xff, 0xf8, 0xff, 0xe1, 0xff, + 0xfb, 0x00, 0x04, 0x00, 0x0b, 0xff, 0xf6, 0x00, 0x03, 0x00, 0x3f, 0x00, 0x47, 0x00, 0x1b, 0x00, 0x2f, 0x00, 0x1c, + 0x00, 0x37, 0x00, 0x44, 0x00, 0x4d, 0x00, 0x33, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x2d, 0xfe, + 0xdb, 0x00, 0x00, 0x0a, 0xf0, 0xfd, 0x5c, 0xfd, 0x9b, 0x0a, 0xdc, 0x03, 0xe8, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04, 0x02, 0x50, 0x02, 0xbc, 0x00, 0x05, 0x00, + 0x00, 0x02, 0x8a, 0x02, 0x58, 0xff, 0xf0, 0x00, 0x4b, 0x02, 0x8a, 0x02, 0x58, 0x00, 0x4a, 0x01, 0x5e, 0x00, 0x32, + 0x01, 0x48, 0x00, 0x00, 0x02, 0x0b, 0x08, 0x02, 0x04, 0x05, 0x04, 0x09, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4f, 0x4f, 0x47, 0x01, 0xa1, 0x00, 0x20, + 0x00, 0x7e, 0x04, 0x2d, 0xfe, 0xdb, 0x00, 0x00, 0x04, 0x64, 0x01, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x22, 0x02, 0xca, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xe1, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x2c, 0x20, 0xb0, 0x00, 0x55, 0x58, 0x45, 0x59, 0x20, 0x20, 0x4b, + 0xb8, 0x00, 0x0e, 0x51, 0x4b, 0xb0, 0x06, 0x53, 0x5a, 0x58, 0xb0, 0x34, 0x1b, 0xb0, 0x28, 0x59, 0x60, 0x66, 0x20, + 0x8a, 0x55, 0x58, 0xb0, 0x02, 0x25, 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x62, 0x1b, 0x21, 0x21, + 0xb0, 0x00, 0x59, 0xb0, 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x01, 0x2c, + 0xb0, 0x20, 0x60, 0x66, 0x2d, 0xb0, 0x02, 0x2c, 0x23, 0x21, 0x23, 0x21, 0x2d, 0xb0, 0x03, 0x2c, 0x20, 0x64, 0xb3, + 0x03, 0x14, 0x15, 0x00, 0x42, 0x43, 0xb0, 0x13, 0x43, 0x20, 0x60, 0x60, 0x42, 0xb1, 0x02, 0x14, 0x43, 0x42, 0xb1, + 0x25, 0x03, 0x43, 0xb0, 0x02, 0x43, 0x54, 0x78, 0x20, 0xb0, 0x0c, 0x23, 0xb0, 0x02, 0x43, 0x43, 0x61, 0x64, 0xb0, + 0x04, 0x50, 0x78, 0xb2, 0x02, 0x02, 0x02, 0x43, 0x60, 0x42, 0xb0, 0x21, 0x65, 0x1c, 0x21, 0xb0, 0x02, 0x43, 0x43, + 0xb2, 0x0e, 0x15, 0x01, 0x42, 0x1c, 0x20, 0xb0, 0x02, 0x43, 0x23, 0x42, 0xb2, 0x13, 0x01, 0x13, 0x43, 0x60, 0x42, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb2, 0x16, 0x01, 0x02, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x04, 0x2c, 0xb0, + 0x03, 0x2b, 0xb0, 0x15, 0x43, 0x58, 0x23, 0x21, 0x23, 0x21, 0xb0, 0x16, 0x43, 0x43, 0x23, 0xb0, 0x00, 0x50, 0x58, + 0x65, 0x59, 0x1b, 0x20, 0x64, 0x20, 0xb0, 0xc0, 0x50, 0xb0, 0x04, 0x26, 0x5a, 0xb2, 0x28, 0x01, 0x0d, 0x43, 0x45, + 0x63, 0x45, 0xb0, 0x06, 0x45, 0x58, 0x21, 0xb0, 0x03, 0x25, 0x59, 0x52, 0x5b, 0x58, 0x21, 0x23, 0x21, 0x1b, 0x8a, + 0x58, 0x20, 0xb0, 0x50, 0x50, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b, 0x20, 0xb0, 0x38, 0x50, 0x58, 0x21, 0xb0, 0x38, + 0x59, 0x59, 0x20, 0xb1, 0x01, 0x0d, 0x43, 0x45, 0x63, 0x45, 0x61, 0x64, 0xb0, 0x28, 0x50, 0x58, 0x21, 0xb1, 0x01, + 0x0d, 0x43, 0x45, 0x63, 0x45, 0x20, 0xb0, 0x30, 0x50, 0x58, 0x21, 0xb0, 0x30, 0x59, 0x1b, 0x20, 0xb0, 0xc0, 0x50, + 0x58, 0x20, 0x66, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x0a, 0x50, 0x58, 0x60, 0x1b, 0x20, 0xb0, 0x20, 0x50, 0x58, + 0x21, 0xb0, 0x0a, 0x60, 0x1b, 0x20, 0xb0, 0x36, 0x50, 0x58, 0x21, 0xb0, 0x36, 0x60, 0x1b, 0x60, 0x59, 0x59, 0x59, + 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x0c, 0x43, 0x63, 0xb0, 0x00, 0x52, 0x58, 0xb0, 0x00, 0x4b, 0xb0, 0x0a, 0x50, 0x58, + 0x21, 0xb0, 0x0c, 0x43, 0x1b, 0x4b, 0xb0, 0x1e, 0x50, 0x58, 0x21, 0xb0, 0x1e, 0x4b, 0x61, 0xb8, 0x10, 0x00, 0x63, + 0xb0, 0x0c, 0x43, 0x63, 0xb8, 0x05, 0x00, 0x62, 0x59, 0x59, 0x64, 0x61, 0x59, 0xb0, 0x01, 0x2b, 0x59, 0x59, 0x23, + 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x59, 0x20, 0x64, 0xb0, 0x16, 0x43, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x05, 0x2c, + 0x20, 0x45, 0x20, 0xb0, 0x04, 0x25, 0x61, 0x64, 0x20, 0xb0, 0x07, 0x43, 0x50, 0x58, 0xb0, 0x07, 0x23, 0x42, 0xb0, + 0x08, 0x23, 0x42, 0x1b, 0x21, 0x21, 0x59, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x06, 0x2c, 0x23, 0x21, 0x23, 0x21, 0xb0, + 0x03, 0x2b, 0x20, 0x64, 0xb1, 0x07, 0x62, 0x42, 0x20, 0xb0, 0x08, 0x23, 0x42, 0xb0, 0x06, 0x45, 0x58, 0x1b, 0xb1, + 0x01, 0x0d, 0x43, 0x45, 0x63, 0xb1, 0x01, 0x0d, 0x43, 0xb0, 0x09, 0x60, 0x45, 0x63, 0xb0, 0x05, 0x2a, 0x21, 0x20, + 0xb0, 0x08, 0x43, 0x20, 0x8a, 0x20, 0x8a, 0xb0, 0x01, 0x2b, 0xb1, 0x30, 0x05, 0x25, 0xb0, 0x04, 0x26, 0x51, 0x58, + 0x60, 0x50, 0x1b, 0x61, 0x52, 0x59, 0x58, 0x23, 0x59, 0x21, 0x59, 0x20, 0xb0, 0x40, 0x53, 0x58, 0xb0, 0x01, 0x2b, + 0x1b, 0x21, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0x2d, 0xb0, 0x07, 0x2c, 0xb0, 0x09, 0x43, + 0x2b, 0xb2, 0x00, 0x02, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x08, 0x2c, 0xb0, 0x09, 0x23, 0x42, 0x23, 0x20, 0xb0, + 0x00, 0x23, 0x42, 0x61, 0xb0, 0x02, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x60, 0xb0, 0x07, 0x2a, 0x2d, 0xb0, + 0x09, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, + 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0a, 0x2c, 0xb2, 0x09, + 0x0e, 0x00, 0x43, 0x45, 0x42, 0x2a, 0x21, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0b, 0x2c, 0xb0, + 0x00, 0x43, 0x23, 0x44, 0xb2, 0x00, 0x01, 0x00, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x0c, 0x2c, 0x20, 0x20, 0x45, 0x20, + 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, 0x8a, 0x23, 0x61, 0x20, 0x64, 0x20, + 0xb0, 0x20, 0x50, 0x58, 0x21, 0xb0, 0x00, 0x1b, 0xb0, 0x30, 0x50, 0x58, 0xb0, 0x20, 0x1b, 0xb0, 0x40, 0x59, 0x59, + 0x23, 0xb0, 0x00, 0x50, 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, + 0x0d, 0x2c, 0x20, 0x20, 0x45, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x00, 0x43, 0xb0, 0x04, 0x25, 0x60, 0x20, 0x45, + 0x8a, 0x23, 0x61, 0x20, 0x64, 0xb0, 0x24, 0x50, 0x58, 0xb0, 0x00, 0x1b, 0xb0, 0x40, 0x59, 0x23, 0xb0, 0x00, 0x50, + 0x58, 0x65, 0x59, 0xb0, 0x03, 0x25, 0x23, 0x61, 0x44, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x0e, 0x2c, 0x20, 0xb0, + 0x00, 0x23, 0x42, 0xb3, 0x0d, 0x0c, 0x00, 0x03, 0x45, 0x50, 0x58, 0x21, 0x1b, 0x23, 0x21, 0x59, 0x2a, 0x21, 0x2d, + 0xb0, 0x0f, 0x2c, 0xb1, 0x02, 0x02, 0x45, 0xb0, 0x64, 0x61, 0x44, 0x2d, 0xb0, 0x10, 0x2c, 0xb0, 0x01, 0x60, 0x20, + 0x20, 0xb0, 0x0f, 0x43, 0x4a, 0xb0, 0x00, 0x50, 0x58, 0x20, 0xb0, 0x0f, 0x23, 0x42, 0x59, 0xb0, 0x10, 0x43, 0x4a, + 0xb0, 0x00, 0x52, 0x58, 0x20, 0xb0, 0x10, 0x23, 0x42, 0x59, 0x2d, 0xb0, 0x11, 0x2c, 0x20, 0xb0, 0x10, 0x62, 0x66, + 0xb0, 0x01, 0x63, 0x20, 0xb8, 0x04, 0x00, 0x63, 0x8a, 0x23, 0x61, 0xb0, 0x11, 0x43, 0x60, 0x20, 0x8a, 0x60, 0x20, + 0xb0, 0x11, 0x23, 0x42, 0x23, 0x2d, 0xb0, 0x12, 0x2c, 0x4b, 0x54, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, 0x24, 0xb0, + 0x0d, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x13, 0x2c, 0x4b, 0x51, 0x58, 0x4b, 0x53, 0x58, 0xb1, 0x04, 0x64, 0x44, 0x59, + 0x1b, 0x21, 0x59, 0x24, 0xb0, 0x13, 0x65, 0x23, 0x78, 0x2d, 0xb0, 0x14, 0x2c, 0xb1, 0x00, 0x12, 0x43, 0x55, 0x58, + 0xb1, 0x12, 0x12, 0x43, 0xb0, 0x01, 0x61, 0x42, 0xb0, 0x11, 0x2b, 0x59, 0xb0, 0x00, 0x43, 0xb0, 0x02, 0x25, 0x42, + 0xb1, 0x0f, 0x02, 0x25, 0x42, 0xb1, 0x10, 0x02, 0x25, 0x42, 0xb0, 0x01, 0x16, 0x23, 0x20, 0xb0, 0x03, 0x25, 0x50, + 0x58, 0xb1, 0x01, 0x00, 0x43, 0x60, 0xb0, 0x04, 0x25, 0x42, 0x8a, 0x8a, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, + 0x21, 0x23, 0xb0, 0x01, 0x61, 0x20, 0x8a, 0x23, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x1b, 0xb1, 0x01, 0x00, 0x43, 0x60, + 0xb0, 0x02, 0x25, 0x42, 0xb0, 0x02, 0x25, 0x61, 0xb0, 0x10, 0x2a, 0x21, 0x59, 0xb0, 0x0f, 0x43, 0x47, 0xb0, 0x10, + 0x43, 0x47, 0x60, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, + 0xb0, 0x01, 0x63, 0x60, 0xb1, 0x00, 0x00, 0x13, 0x23, 0x44, 0xb0, 0x01, 0x43, 0xb0, 0x00, 0x3e, 0xb2, 0x01, 0x01, + 0x01, 0x43, 0x60, 0x42, 0x2d, 0xb0, 0x15, 0x2c, 0x00, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, 0xb0, 0x12, 0x23, 0x42, + 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, 0xb7, 0x18, 0x18, 0x01, + 0x00, 0x11, 0x00, 0x13, 0x00, 0x42, 0x42, 0x42, 0x8a, 0x60, 0x20, 0xb0, 0x14, 0x23, 0x42, 0xb0, 0x01, 0x61, 0xb1, + 0x14, 0x08, 0x2b, 0xb0, 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x16, 0x2c, 0xb1, 0x00, 0x15, 0x2b, 0x2d, 0xb0, + 0x17, 0x2c, 0xb1, 0x01, 0x15, 0x2b, 0x2d, 0xb0, 0x18, 0x2c, 0xb1, 0x02, 0x15, 0x2b, 0x2d, 0xb0, 0x19, 0x2c, 0xb1, + 0x03, 0x15, 0x2b, 0x2d, 0xb0, 0x1a, 0x2c, 0xb1, 0x04, 0x15, 0x2b, 0x2d, 0xb0, 0x1b, 0x2c, 0xb1, 0x05, 0x15, 0x2b, + 0x2d, 0xb0, 0x1c, 0x2c, 0xb1, 0x06, 0x15, 0x2b, 0x2d, 0xb0, 0x1d, 0x2c, 0xb1, 0x07, 0x15, 0x2b, 0x2d, 0xb0, 0x1e, + 0x2c, 0xb1, 0x08, 0x15, 0x2b, 0x2d, 0xb0, 0x1f, 0x2c, 0xb1, 0x09, 0x15, 0x2b, 0x2d, 0xb0, 0x2b, 0x2c, 0x23, 0x20, + 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x06, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x5d, + 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2c, 0x2c, 0x23, 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x16, + 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, 0x71, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x2d, 0x2c, 0x23, + 0x20, 0xb0, 0x10, 0x62, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x26, 0x60, 0x4b, 0x54, 0x58, 0x23, 0x20, 0x2e, 0xb0, 0x01, + 0x72, 0x1b, 0x21, 0x21, 0x59, 0x2d, 0xb0, 0x20, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, 0x54, 0x58, + 0xb0, 0x12, 0x23, 0x42, 0x20, 0x45, 0xb0, 0x0e, 0x23, 0x42, 0xb0, 0x0d, 0x23, 0xb0, 0x09, 0x60, 0x42, 0x20, 0x60, + 0xb0, 0x01, 0x61, 0xb5, 0x18, 0x18, 0x01, 0x00, 0x11, 0x00, 0x42, 0x42, 0x8a, 0x60, 0xb1, 0x14, 0x08, 0x2b, 0xb0, + 0x8b, 0x2b, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x21, 0x2c, 0xb1, 0x00, 0x20, 0x2b, 0x2d, 0xb0, 0x22, 0x2c, 0xb1, 0x01, + 0x20, 0x2b, 0x2d, 0xb0, 0x23, 0x2c, 0xb1, 0x02, 0x20, 0x2b, 0x2d, 0xb0, 0x24, 0x2c, 0xb1, 0x03, 0x20, 0x2b, 0x2d, + 0xb0, 0x25, 0x2c, 0xb1, 0x04, 0x20, 0x2b, 0x2d, 0xb0, 0x26, 0x2c, 0xb1, 0x05, 0x20, 0x2b, 0x2d, 0xb0, 0x27, 0x2c, + 0xb1, 0x06, 0x20, 0x2b, 0x2d, 0xb0, 0x28, 0x2c, 0xb1, 0x07, 0x20, 0x2b, 0x2d, 0xb0, 0x29, 0x2c, 0xb1, 0x08, 0x20, + 0x2b, 0x2d, 0xb0, 0x2a, 0x2c, 0xb1, 0x09, 0x20, 0x2b, 0x2d, 0xb0, 0x2e, 0x2c, 0x20, 0x3c, 0xb0, 0x01, 0x60, 0x2d, + 0xb0, 0x2f, 0x2c, 0x20, 0x60, 0xb0, 0x18, 0x60, 0x20, 0x43, 0x23, 0xb0, 0x01, 0x60, 0x43, 0xb0, 0x02, 0x25, 0x61, + 0xb0, 0x01, 0x60, 0xb0, 0x2e, 0x2a, 0x21, 0x2d, 0xb0, 0x30, 0x2c, 0xb0, 0x2f, 0x2b, 0xb0, 0x2f, 0x2a, 0x2d, 0xb0, + 0x31, 0x2c, 0x20, 0x20, 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, + 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x23, 0x20, 0x8a, 0x55, 0x58, 0x20, + 0x47, 0x20, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, + 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x61, 0x38, 0x1b, 0x21, 0x59, 0x2d, 0xb0, 0x32, 0x2c, 0x00, 0xb1, 0x00, + 0x02, 0x45, 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, + 0x45, 0x58, 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x33, 0x2c, 0x00, 0xb0, 0x0f, 0x2b, 0xb1, 0x00, 0x02, 0x45, + 0x54, 0x58, 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x16, 0xb0, 0x31, 0x2a, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, + 0x30, 0x59, 0x1b, 0x22, 0x59, 0x2d, 0xb0, 0x34, 0x2c, 0x20, 0x35, 0xb0, 0x01, 0x60, 0x2d, 0xb0, 0x35, 0x2c, 0x00, + 0xb1, 0x0e, 0x06, 0x45, 0x42, 0xb0, 0x01, 0x45, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x01, 0x2b, 0xb0, 0x00, 0x16, 0xb4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x3e, 0x23, 0x38, 0xb1, 0x34, 0x01, 0x15, 0x2a, 0x21, 0x2d, 0xb0, 0x36, 0x2c, + 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0x38, 0x2d, 0xb0, 0x37, 0x2c, 0x2e, 0x17, + 0x3c, 0x2d, 0xb0, 0x38, 0x2c, 0x20, 0x3c, 0x20, 0x47, 0x20, 0xb0, 0x0e, 0x43, 0x63, 0xb8, 0x04, 0x00, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0xb0, 0x00, 0x43, 0x61, 0xb0, 0x01, + 0x43, 0x63, 0x38, 0x2d, 0xb0, 0x39, 0x2c, 0xb1, 0x02, 0x00, 0x16, 0x25, 0x20, 0x2e, 0x20, 0x47, 0xb0, 0x00, 0x23, + 0x42, 0xb0, 0x02, 0x25, 0x49, 0x8a, 0x8a, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0xb0, + 0x01, 0x23, 0x42, 0xb2, 0x38, 0x01, 0x01, 0x15, 0x14, 0x2a, 0x2d, 0xb0, 0x3a, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, + 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, + 0x43, 0x2b, 0x65, 0x8a, 0x2e, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, 0x2d, 0xb0, 0x3b, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x06, + 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, 0x51, + 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0xb0, 0x0a, + 0x43, 0x20, 0x8a, 0x23, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, 0x46, 0x60, 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, + 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, + 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, + 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, + 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x1b, + 0x23, 0xb0, 0x0a, 0x43, 0x46, 0xb0, 0x02, 0x25, 0xb0, 0x0a, 0x43, 0x47, 0x23, 0x47, 0x23, 0x61, 0x60, 0x20, 0xb0, + 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, + 0x23, 0x20, 0xb0, 0x01, 0x2b, 0x23, 0xb0, 0x06, 0x43, 0x60, 0xb0, 0x01, 0x2b, 0xb0, 0x05, 0x25, 0x61, 0xb0, 0x05, + 0x25, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0xb0, 0x04, + 0x26, 0x61, 0x20, 0xb0, 0x04, 0x25, 0x60, 0x64, 0x23, 0xb0, 0x03, 0x25, 0x60, 0x64, 0x50, 0x58, 0x21, 0x1b, 0x23, + 0x21, 0x59, 0x23, 0x20, 0x20, 0xb0, 0x04, 0x26, 0x23, 0x46, 0x61, 0x38, 0x59, 0x2d, 0xb0, 0x3c, 0x2c, 0xb0, 0x00, + 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0x20, 0x20, 0xb0, 0x05, 0x26, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x23, + 0x3c, 0x38, 0x2d, 0xb0, 0x3d, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, 0xb0, 0x0a, 0x23, 0x42, 0x20, + 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, 0x38, 0x2d, 0xb0, 0x3e, 0x2c, 0xb0, 0x00, 0x16, 0xb0, + 0x17, 0x23, 0x42, 0xb0, 0x03, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x00, 0x54, 0x58, 0x2e, + 0x20, 0x3c, 0x23, 0x21, 0x1b, 0xb0, 0x02, 0x25, 0xb0, 0x02, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, 0x05, + 0x25, 0xb0, 0x04, 0x25, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x06, 0x25, 0xb0, 0x05, 0x25, 0x49, 0xb0, 0x02, 0x25, + 0x61, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x63, 0x23, 0x20, 0x58, 0x62, 0x1b, 0x21, 0x59, 0x63, 0xb8, 0x04, 0x00, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x60, 0x23, 0x2e, 0x23, 0x20, + 0x20, 0x3c, 0x8a, 0x38, 0x23, 0x21, 0x59, 0x2d, 0xb0, 0x3f, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x17, 0x23, 0x42, 0x20, + 0xb0, 0x0a, 0x43, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0x60, 0xb0, 0x20, 0x60, 0x66, 0xb0, 0x02, 0x62, + 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x23, 0x20, 0x20, 0x3c, 0x8a, 0x38, + 0x2d, 0xb0, 0x40, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, + 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x41, 0x2c, 0x23, 0x20, 0x2e, 0x46, + 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x42, 0x2c, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, + 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x52, 0x1b, 0x50, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x43, 0x2c, + 0xb0, 0x3a, 0x2b, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, 0x58, 0x50, 0x1b, 0x52, 0x59, + 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x44, 0x2c, 0xb0, 0x3b, 0x2b, 0x8a, 0x20, + 0x20, 0x3c, 0xb0, 0x06, 0x23, 0x42, 0x8a, 0x38, 0x23, 0x20, 0x2e, 0x46, 0xb0, 0x02, 0x25, 0x46, 0xb0, 0x17, 0x43, + 0x58, 0x50, 0x1b, 0x52, 0x59, 0x58, 0x20, 0x3c, 0x59, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, + 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x45, 0x2c, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x26, 0x20, 0x20, 0x20, + 0x46, 0x23, 0x47, 0x61, 0xb0, 0x0c, 0x23, 0x42, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0xb0, 0x0b, 0x43, 0x2b, 0x23, + 0x20, 0x3c, 0x20, 0x2e, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x46, 0x2c, 0xb1, 0x0a, 0x04, 0x25, + 0x42, 0xb0, 0x00, 0x16, 0xb0, 0x04, 0x25, 0xb0, 0x04, 0x25, 0x20, 0x2e, 0x47, 0x23, 0x47, 0x23, 0x61, 0x20, 0xb0, + 0x06, 0x23, 0x42, 0xb1, 0x0c, 0x00, 0x42, 0xb0, 0x0b, 0x43, 0x2b, 0x20, 0xb0, 0x60, 0x50, 0x58, 0x20, 0xb0, 0x40, + 0x51, 0x58, 0xb3, 0x04, 0x20, 0x05, 0x20, 0x1b, 0xb3, 0x04, 0x26, 0x05, 0x1a, 0x59, 0x42, 0x42, 0x23, 0x20, 0x47, + 0xb0, 0x06, 0x43, 0xb0, 0x02, 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, + 0x60, 0x20, 0xb0, 0x01, 0x2b, 0x20, 0x8a, 0x8a, 0x61, 0x20, 0xb0, 0x04, 0x43, 0x60, 0x64, 0x23, 0xb0, 0x05, 0x43, + 0x61, 0x64, 0x50, 0x58, 0xb0, 0x04, 0x43, 0x61, 0x1b, 0xb0, 0x05, 0x43, 0x60, 0x59, 0xb0, 0x03, 0x25, 0xb0, 0x02, + 0x62, 0x20, 0xb0, 0x00, 0x50, 0x58, 0xb0, 0x40, 0x60, 0x59, 0x66, 0xb0, 0x01, 0x63, 0x61, 0xb0, 0x02, 0x25, 0x46, + 0x61, 0x38, 0x23, 0x20, 0x3c, 0x23, 0x38, 0x1b, 0x21, 0x20, 0x20, 0x46, 0x23, 0x47, 0xb0, 0x01, 0x2b, 0x23, 0x61, + 0x38, 0x21, 0x59, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x47, 0x2c, 0xb1, 0x00, 0x3a, 0x2b, 0x2e, 0xb1, 0x30, + 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x48, 0x2c, 0xb1, 0x00, 0x3b, 0x2b, 0x21, 0x23, 0x20, 0x20, 0x3c, 0xb0, 0x06, 0x23, + 0x42, 0x23, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0xb0, 0x06, 0x43, 0x2e, 0xb0, 0x30, 0x2b, 0x2d, 0xb0, 0x49, 0x2c, + 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, 0x14, 0x13, 0x2e, 0xb0, 0x36, + 0x2a, 0x2d, 0xb0, 0x4a, 0x2c, 0xb0, 0x00, 0x15, 0x20, 0x47, 0xb0, 0x00, 0x23, 0x42, 0xb2, 0x00, 0x01, 0x01, 0x15, + 0x14, 0x13, 0x2e, 0xb0, 0x36, 0x2a, 0x2d, 0xb0, 0x4b, 0x2c, 0xb1, 0x00, 0x01, 0x14, 0x13, 0xb0, 0x37, 0x2a, 0x2d, + 0xb0, 0x4c, 0x2c, 0xb0, 0x39, 0x2a, 0x2d, 0xb0, 0x4d, 0x2c, 0xb0, 0x00, 0x16, 0x45, 0x23, 0x20, 0x2e, 0x20, 0x46, + 0x8a, 0x23, 0x61, 0x38, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x4e, 0x2c, 0xb0, 0x0a, 0x23, 0x42, 0xb0, 0x4d, + 0x2b, 0x2d, 0xb0, 0x4f, 0x2c, 0xb2, 0x00, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x50, 0x2c, 0xb2, 0x00, 0x01, 0x46, 0x2b, + 0x2d, 0xb0, 0x51, 0x2c, 0xb2, 0x01, 0x00, 0x46, 0x2b, 0x2d, 0xb0, 0x52, 0x2c, 0xb2, 0x01, 0x01, 0x46, 0x2b, 0x2d, + 0xb0, 0x53, 0x2c, 0xb2, 0x00, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x54, 0x2c, 0xb2, 0x00, 0x01, 0x47, 0x2b, 0x2d, 0xb0, + 0x55, 0x2c, 0xb2, 0x01, 0x00, 0x47, 0x2b, 0x2d, 0xb0, 0x56, 0x2c, 0xb2, 0x01, 0x01, 0x47, 0x2b, 0x2d, 0xb0, 0x57, + 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x58, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x43, 0x2b, 0x2d, 0xb0, + 0x59, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x43, 0x2b, 0x2d, 0xb0, 0x5a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x43, 0x2b, 0x2d, + 0xb0, 0x5b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x43, 0x2b, + 0x2d, 0xb0, 0x5d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x43, 0x2b, 0x2d, 0xb0, 0x5e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x43, + 0x2b, 0x2d, 0xb0, 0x5f, 0x2c, 0xb2, 0x00, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x60, 0x2c, 0xb2, 0x00, 0x01, 0x45, 0x2b, + 0x2d, 0xb0, 0x61, 0x2c, 0xb2, 0x01, 0x00, 0x45, 0x2b, 0x2d, 0xb0, 0x62, 0x2c, 0xb2, 0x01, 0x01, 0x45, 0x2b, 0x2d, + 0xb0, 0x63, 0x2c, 0xb2, 0x00, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x64, 0x2c, 0xb2, 0x00, 0x01, 0x48, 0x2b, 0x2d, 0xb0, + 0x65, 0x2c, 0xb2, 0x01, 0x00, 0x48, 0x2b, 0x2d, 0xb0, 0x66, 0x2c, 0xb2, 0x01, 0x01, 0x48, 0x2b, 0x2d, 0xb0, 0x67, + 0x2c, 0xb3, 0x00, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x68, 0x2c, 0xb3, 0x00, 0x01, 0x00, 0x44, 0x2b, 0x2d, 0xb0, + 0x69, 0x2c, 0xb3, 0x01, 0x00, 0x00, 0x44, 0x2b, 0x2d, 0xb0, 0x6a, 0x2c, 0xb3, 0x01, 0x01, 0x00, 0x44, 0x2b, 0x2d, + 0xb0, 0x6b, 0x2c, 0xb3, 0x00, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6c, 0x2c, 0xb3, 0x00, 0x01, 0x01, 0x44, 0x2b, + 0x2d, 0xb0, 0x6d, 0x2c, 0xb3, 0x01, 0x00, 0x01, 0x44, 0x2b, 0x2d, 0xb0, 0x6e, 0x2c, 0xb3, 0x01, 0x01, 0x01, 0x44, + 0x2b, 0x2d, 0xb0, 0x6f, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x70, 0x2c, + 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x71, 0x2c, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, + 0xb0, 0x72, 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x00, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x73, 0x2c, 0xb1, 0x01, + 0x3c, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x74, 0x2c, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x75, + 0x2c, 0xb0, 0x00, 0x16, 0xb1, 0x01, 0x3c, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x76, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, + 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x77, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, + 0x78, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x79, 0x2c, 0xb1, 0x00, 0x3d, 0x2b, 0xb0, 0x42, + 0x2b, 0x2d, 0xb0, 0x7a, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x7b, 0x2c, 0xb1, 0x01, 0x3d, + 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x7c, 0x2c, 0xb1, 0x01, 0x3d, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x7d, 0x2c, + 0xb1, 0x00, 0x3e, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x7e, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, + 0x40, 0x2b, 0x2d, 0xb0, 0x7f, 0x2c, 0xb1, 0x00, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x80, 0x2c, 0xb1, 0x00, + 0x3e, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x81, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x82, + 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x83, 0x2c, 0xb1, 0x01, 0x3e, 0x2b, 0xb0, 0x42, 0x2b, + 0x2d, 0xb0, 0x84, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0x2e, 0xb1, 0x30, 0x01, 0x14, 0x2b, 0x2d, 0xb0, 0x85, 0x2c, 0xb1, + 0x00, 0x3f, 0x2b, 0xb0, 0x40, 0x2b, 0x2d, 0xb0, 0x86, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, + 0x87, 0x2c, 0xb1, 0x00, 0x3f, 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x88, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x40, + 0x2b, 0x2d, 0xb0, 0x89, 0x2c, 0xb1, 0x01, 0x3f, 0x2b, 0xb0, 0x41, 0x2b, 0x2d, 0xb0, 0x8a, 0x2c, 0xb1, 0x01, 0x3f, + 0x2b, 0xb0, 0x42, 0x2b, 0x2d, 0xb0, 0x8b, 0x2c, 0xb2, 0x0b, 0x00, 0x03, 0x45, 0x50, 0x58, 0xb0, 0x06, 0x1b, 0xb2, + 0x04, 0x02, 0x03, 0x45, 0x58, 0x23, 0x21, 0x1b, 0x21, 0x59, 0x59, 0x42, 0x2b, 0xb0, 0x08, 0x65, 0xb0, 0x03, 0x24, + 0x50, 0x78, 0xb1, 0x05, 0x01, 0x15, 0x45, 0x58, 0x30, 0x59, 0x2d, 0x00, 0x4b, 0xb8, 0x00, 0xc8, 0x52, 0x58, 0xb1, + 0x01, 0x01, 0x8e, 0x59, 0xb0, 0x01, 0xb9, 0x08, 0x00, 0x08, 0x00, 0x63, 0x70, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x0b, + 0x93, 0x83, 0x73, 0x00, 0x5d, 0x00, 0x49, 0x39, 0x2d, 0x09, 0x00, 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x88, + 0x08, 0x78, 0x08, 0x68, 0x08, 0x62, 0x02, 0x56, 0x06, 0x4e, 0x04, 0x3e, 0x08, 0x32, 0x06, 0x24, 0x07, 0x09, 0x0a, + 0x2a, 0xb1, 0x00, 0x07, 0x42, 0x40, 0x14, 0x90, 0x06, 0x80, 0x06, 0x70, 0x06, 0x65, 0x00, 0x5c, 0x04, 0x52, 0x02, + 0x46, 0x06, 0x38, 0x04, 0x2b, 0x05, 0x09, 0x0a, 0x2a, 0xb1, 0x00, 0x10, 0x42, 0x41, 0x0b, 0x22, 0x40, 0x1e, 0x40, + 0x1a, 0x40, 0x18, 0xc0, 0x15, 0xc0, 0x13, 0xc0, 0x0f, 0xc0, 0x0c, 0xc0, 0x09, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, + 0xb1, 0x00, 0x19, 0x42, 0x41, 0x0b, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x09, 0x00, 0x0b, 0x2a, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0xb1, 0x24, 0x01, + 0x88, 0x51, 0x58, 0xb0, 0x40, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x64, 0x44, 0xb1, 0x28, 0x01, 0x88, 0x51, 0x58, + 0xb8, 0x08, 0x00, 0x88, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x1b, 0xb1, 0x27, 0x01, 0x88, 0x51, 0x58, + 0xba, 0x08, 0x80, 0x00, 0x01, 0x04, 0x40, 0x88, 0x63, 0x54, 0x58, 0xb9, 0x00, 0x03, 0x00, 0x00, 0x44, 0x59, 0x59, + 0x59, 0x59, 0x59, 0x40, 0x14, 0x8a, 0x06, 0x7a, 0x06, 0x6a, 0x06, 0x64, 0x01, 0x58, 0x04, 0x50, 0x02, 0x40, 0x06, + 0x34, 0x04, 0x26, 0x05, 0x09, 0x0e, 0x2a, 0xb8, 0x01, 0xff, 0x85, 0xb0, 0x04, 0x8d, 0xb1, 0x02, 0x00, 0x44, 0xb3, + 0x05, 0x64, 0x06, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x73, 0x02, 0xca, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0xff, 0x10, + 0x02, 0xd6, 0xff, 0xf6, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, + 0x46, 0x02, 0x46, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x94, 0x00, 0x94, + 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0xff, 0xf6, 0x02, 0xf8, 0x02, 0x22, 0xff, 0xf6, 0xff, 0x10, 0x02, 0xd5, 0xff, + 0xf6, 0x02, 0xfd, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x99, 0x00, 0x99, 0x00, 0x7d, 0x00, 0x7d, 0x02, 0x46, + 0x00, 0x00, 0x02, 0x50, 0xff, 0xf8, 0x00, 0x78, 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, 0x01, 0x68, 0x00, 0xee, 0xff, + 0xa0, 0xff, 0x10, 0x01, 0x68, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x78, 0x00, 0x78, 0x00, 0x65, 0x00, 0x65, + 0x01, 0x1f, 0x01, 0x1f, 0x00, 0x94, 0x00, 0x94, 0x00, 0x78, 0x00, 0x78, 0x02, 0xca, 0x00, 0x00, 0x02, 0xf8, 0x02, + 0x22, 0x00, 0x00, 0xff, 0x10, 0x02, 0xd5, 0xff, 0xf6, 0x02, 0xf9, 0x02, 0x2c, 0xff, 0xf6, 0xff, 0x10, 0x00, 0x60, + 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, 0x01, 0x29, 0xff, 0x7d, 0x01, 0x68, 0x00, 0xe8, 0xff, 0xa0, 0xff, 0x10, 0x01, + 0x33, 0xff, 0x73, 0x01, 0x69, 0x00, 0xee, 0xff, 0x9a, 0xff, 0x10, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x48, + 0x02, 0xcb, 0x01, 0x9f, 0x02, 0xe7, 0x02, 0x67, 0x01, 0x1f, 0x00, 0x8f, 0x02, 0xe8, 0x01, 0x95, 0x02, 0xe8, 0x02, + 0x6d, 0x01, 0x19, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x00, + 0x00, 0xb6, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x12, 0x00, 0xb6, 0x00, 0x03, 0x00, + 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x16, 0x00, 0xc8, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x3c, + 0x00, 0xde, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x04, 0x00, 0x2a, 0x01, 0x1a, 0x00, 0x03, 0x00, 0x01, 0x04, + 0x09, 0x00, 0x05, 0x00, 0x54, 0x01, 0x44, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x26, 0x01, 0x98, + 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, + 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x32, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, + 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6a, 0x00, + 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, + 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3a, 0x00, + 0x2f, 0x00, 0x2f, 0x00, 0x67, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x63, + 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2f, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x6f, 0x00, + 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2d, + 0x00, 0x67, 0x00, 0x72, 0x00, 0x65, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x2d, 0x00, 0x63, 0x00, 0x79, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, + 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, + 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x4f, 0x00, 0x47, 0x00, 0x3b, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, + 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x4e, 0x00, + 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x53, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x20, 0x00, 0x42, + 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x20, 0x00, 0x49, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x32, + 0x00, 0x2e, 0x00, 0x30, 0x00, 0x31, 0x00, 0x35, 0x00, 0x3b, 0x00, 0x20, 0x00, 0x74, 0x00, 0x74, 0x00, 0x66, 0x00, + 0x61, 0x00, 0x75, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x28, + 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x2d, 0x00, + 0x35, 0x00, 0x64, 0x00, 0x35, 0x00, 0x62, 0x00, 0x29, 0x00, 0x4e, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x64, 0x00, 0x49, 0x00, + 0x74, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x03, 0x00, 0x00, 0xff, 0xf4, 0x00, 0x00, 0xff, 0x9c, + 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x22, 0x00, 0x3b, 0x00, 0x01, 0x00, 0x42, 0x00, 0x5b, 0x00, + 0x01, 0x00, 0x6b, 0x00, 0x6b, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x02, 0x00, 0x18, 0x00, 0x0a, 0x00, 0x22, + 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, 0x2a, 0x00, 0x32, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x4e, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x01, 0x21, 0x00, 0x01, + 0x00, 0x04, 0x00, 0x01, 0x01, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x1f, 0x00, 0x01, 0x02, + 0x73, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x01, 0x25, 0x00, 0x01, 0x02, 0x7d, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x01, 0x01, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x00, 0x40, 0x00, 0x04, 0x44, + 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, + 0x74, 0x6e, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, + 0x65, 0x72, 0x6e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x06, 0xc8, + 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0x01, 0x08, 0x00, 0x01, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x6a, 0x00, 0xf4, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x8c, 0x00, 0xb4, 0x00, 0x92, 0x00, 0x98, 0x00, 0xb4, + 0x00, 0xaa, 0x00, 0xb4, 0x00, 0xba, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xce, 0x00, 0xd8, 0x00, 0xf4, 0x00, 0xde, 0x00, + 0xe4, 0x00, 0xee, 0x00, 0xee, 0x00, 0xee, 0x00, 0xf4, 0x00, 0x01, 0x00, 0x17, 0x00, 0x07, 0x00, 0x09, 0x00, 0x22, + 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, + 0x37, 0x00, 0x38, 0x00, 0x3a, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x44, 0x00, 0x57, 0x00, 0x58, 0x00, 0x5a, + 0x00, 0x5c, 0x00, 0x04, 0x00, 0x35, 0xff, 0xc4, 0x00, 0x37, 0xff, 0xd8, 0x00, 0x38, 0xff, 0xd8, 0x00, 0x3a, 0xff, + 0xc4, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x4b, 0x00, 0x02, 0x00, 0x0d, 0xff, 0xec, 0x00, 0x0f, 0xff, 0xec, 0x00, 0x01, + 0x00, 0x07, 0xff, 0xf6, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x3c, 0x00, 0x04, 0x00, 0x0d, 0xff, 0xc4, 0x00, 0x0f, 0xff, + 0xc4, 0x00, 0x20, 0x00, 0x14, 0x00, 0x22, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x39, 0xff, 0xec, + 0x00, 0x01, 0x00, 0x39, 0xff, 0xec, 0x00, 0x02, 0x00, 0x07, 0xff, 0xec, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, + 0x07, 0xff, 0xf6, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x07, 0xff, 0xe2, 0x00, 0x20, 0x00, 0x14, 0x00, 0x01, + 0x00, 0x07, 0xff, 0xec, 0x00, 0x01, 0x00, 0x2b, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x14, 0x00, 0x08, 0x00, + 0x14, 0x00, 0x01, 0x00, 0x20, 0x00, 0x14, 0x00, 0x02, 0x00, 0x2b, 0x00, 0x5a, 0x00, 0x4b, 0x00, 0x28, 0x00, 0x02, + 0x03, 0xd8, 0x00, 0x04, 0x00, 0x00, 0x04, 0x26, 0x04, 0xe4, 0x00, 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe2, + 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xe2, 0xff, + 0xd8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0xff, 0xec, 0xff, + 0xe2, 0xff, 0xce, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0xff, 0xc4, + 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, + 0x00, 0x00, 0xff, 0xd8, 0xff, 0xec, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xff, 0xf6, 0xff, 0xf6, + 0xff, 0xec, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0xff, 0xce, 0xff, + 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xc4, 0x00, 0x00, 0xff, 0xe2, 0xff, 0xd8, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x14, 0xff, + 0xe2, 0x00, 0x14, 0x00, 0x00, 0xff, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xba, 0xff, 0xec, 0xff, 0xce, 0xff, 0xb0, 0xff, 0xce, 0x00, 0x00, 0xff, + 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x0a, 0xff, 0xc4, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, + 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, + 0xff, 0xc4, 0xff, 0xc4, 0x00, 0x00, 0xff, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8e, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x22, 0x00, 0x24, 0x00, 0x25, 0x00, 0x2c, 0x00, + 0x2d, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00, 0x3a, + 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x43, 0x00, 0x46, 0x00, 0x47, 0x00, 0x4c, 0x00, 0x50, 0x00, 0x51, 0x00, + 0x53, 0x00, 0x55, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5c, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x1f, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x09, 0x00, 0x13, 0x00, + 0x0d, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x22, + 0x00, 0x22, 0x00, 0x01, 0x00, 0x24, 0x00, 0x24, 0x00, 0x07, 0x00, 0x25, 0x00, 0x25, 0x00, 0x03, 0x00, 0x2c, 0x00, + 0x2c, 0x00, 0x12, 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x03, 0x00, 0x31, 0x00, 0x31, + 0x00, 0x14, 0x00, 0x32, 0x00, 0x32, 0x00, 0x03, 0x00, 0x35, 0x00, 0x35, 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, + 0x05, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x39, 0x00, 0x39, 0x00, 0x12, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x06, + 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0d, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x02, 0x00, + 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x10, 0x00, 0x53, 0x00, 0x53, 0x00, 0x11, 0x00, 0x55, + 0x00, 0x55, 0x00, 0x0c, 0x00, 0x57, 0x00, 0x58, 0x00, 0x04, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x00, 0x5a, 0x00, + 0x5a, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x15, 0x00, 0x02, 0x00, 0x23, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x11, 0x00, 0x08, 0x00, 0x08, 0x00, 0x11, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x13, 0x00, + 0x0d, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x1b, + 0x00, 0x1c, 0x00, 0x14, 0x00, 0x22, 0x00, 0x22, 0x00, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x02, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x02, 0x00, 0x30, 0x00, 0x30, 0x00, 0x02, 0x00, 0x32, 0x00, 0x32, 0x00, 0x02, 0x00, 0x35, 0x00, 0x35, + 0x00, 0x0b, 0x00, 0x36, 0x00, 0x36, 0x00, 0x06, 0x00, 0x37, 0x00, 0x38, 0x00, 0x09, 0x00, 0x3a, 0x00, 0x3a, 0x00, + 0x08, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x13, 0x00, 0x42, 0x00, 0x42, 0x00, 0x04, + 0x00, 0x44, 0x00, 0x46, 0x00, 0x01, 0x00, 0x47, 0x00, 0x47, 0x00, 0x15, 0x00, 0x48, 0x00, 0x48, 0x00, 0x0d, 0x00, + 0x4e, 0x00, 0x4f, 0x00, 0x03, 0x00, 0x50, 0x00, 0x50, 0x00, 0x01, 0x00, 0x51, 0x00, 0x51, 0x00, 0x03, 0x00, 0x52, + 0x00, 0x52, 0x00, 0x01, 0x00, 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x54, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x55, 0x00, + 0x55, 0x00, 0x0e, 0x00, 0x56, 0x00, 0x56, 0x00, 0x03, 0x00, 0x57, 0x00, 0x58, 0x00, 0x07, 0x00, 0x5a, 0x00, 0x5a, + 0x00, 0x07, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x5e, 0x00, 0x13, 0x00, 0x6c, 0x00, 0x6c, 0x00, + 0x15, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x22, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, + 0x00, 0x02, 0x00, 0x0d, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x50, 0x00, 0x92, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x1a, 0x63, 0x79, 0x72, 0x6c, + 0x00, 0x1a, 0x67, 0x72, 0x65, 0x6b, 0x00, 0x1a, 0x6c, 0x61, 0x74, 0x6e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x01, 0x45, 0x57, 0x45, 0x20, 0x00, 0x18, 0x00, 0x00, 0xff, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0xff, 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x04, 0x00, 0x05, 0x64, 0x6e, 0x6f, 0x6d, 0x00, 0x20, 0x66, 0x72, 0x61, 0x63, 0x00, 0x26, 0x6c, 0x69, 0x67, 0x61, + 0x00, 0x30, 0x6c, 0x6f, 0x63, 0x6c, 0x00, 0x36, 0x6e, 0x75, 0x6d, 0x72, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, 0x12, 0x00, 0x5e, 0x00, 0x3c, 0x00, + 0x4a, 0x00, 0x5e, 0x00, 0x76, 0x00, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, + 0x00, 0x12, 0x00, 0x06, 0x00, 0x6b, 0x00, 0x71, 0x00, 0x72, 0x00, 0x73, 0x00, 0x74, 0x00, 0x75, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x47, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x08, 0x00, 0x01, 0x00, 0x28, 0x00, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, + 0x06, 0x00, 0x53, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, + 0x00, 0x06, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x0a, 0x00, 0x22, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x63, 0x00, 0x03, 0x00, 0x01, 0x00, 0x12, 0x00, 0x01, 0x00, + 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x01, 0x00, 0x76, 0x00, 0x7f, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0xff, 0xf6, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x80, 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x66, 0x00, 0x02, + 0x00, 0x0a, 0x00, 0x38, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x6e, 0x00, + 0x03, 0x00, 0x47, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x47, 0x00, 0x4a, 0x00, 0x6f, 0x00, 0x02, 0x00, 0x4a, + 0x00, 0x70, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x6c, 0x00, 0x02, 0x00, 0x47, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x14, 0x00, + 0x1c, 0x00, 0x22, 0x00, 0x28, 0x00, 0x73, 0x00, 0x03, 0x00, 0x6b, 0x00, 0x4d, 0x00, 0x72, 0x00, 0x03, 0x00, 0x6b, + 0x00, 0x4a, 0x00, 0x74, 0x00, 0x02, 0x00, 0x4a, 0x00, 0x75, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x71, 0x00, 0x02, 0x00, + 0x6b, 0x00, 0x01, 0x00, 0x02, 0x00, 0x47, 0x00, 0x6b}; + + constexpr Info FONTS[COUNT] = {{.data = REGULAR_DATA, .length = std::size(REGULAR_DATA)}, + {.data = ITALICS_DATA, .length = std::size(ITALICS_DATA)}, + {.data = BOLD_DATA, .length = std::size(BOLD_DATA)}, + {.data = BOLD_ITALICS_DATA, .length = std::size(BOLD_ITALICS_DATA)}}; + +}; + +namespace anm2ed::resource +{ + class Font + { + ImFont* pointer{}; + + public: + Font(); + Font(void*, size_t, int); + ~Font(); + ImFont* get(); + Font& operator=(Font&&) noexcept; + }; +} diff --git a/src/resource/icon.h b/src/resource/icon.h new file mode 100644 index 0000000..784faf3 --- /dev/null +++ b/src/resource/icon.h @@ -0,0 +1,229 @@ +#pragma once +#include +#include + +namespace anm2ed::resource::icon +{ + constexpr auto SIZE_SMALL = glm::ivec2(64, 64); + constexpr auto SIZE_NORMAL = glm::ivec2(128, 128); + constexpr auto SIZE_LARGE = glm::ivec2(256, 256); + constexpr auto SIZE_HUGE = glm::ivec2(512, 512); + + constexpr auto NONE_DATA = R"( + + )"; + + constexpr auto FILE_DATA = R"( + + )"; + + constexpr auto FOLDER_DATA = R"( + + )"; + + constexpr auto CLOSE_DATA = R"( + + )"; + + constexpr auto ROOT_DATA = R"( + + )"; + + constexpr auto LAYER_DATA = R"( + + )"; + + constexpr auto NULL_DATA = R"( + + )"; + + constexpr auto TRIGGERS_DATA = R"( + + )"; + + constexpr auto VISIBLE_DATA = R"( + + )"; + + constexpr auto INVISIBLE_DATA = R"( + + )"; + + constexpr auto SHOW_UNUSED_DATA = R"( + +)"; + + constexpr auto HIDE_UNUSED_DATA = R"( + +)"; + + constexpr auto SHOW_LAYERS_DATA = R"( + +)"; + + constexpr auto HIDE_LAYERS_DATA = R"( + +)"; + + constexpr auto SHOW_RECT_DATA = R"( + + )"; + + constexpr auto HIDE_RECT_DATA = R"( + + )"; + + constexpr auto ANIMATION_DATA = R"( + + )"; + + constexpr auto SPRITESHEET_DATA = R"( + + )"; + + constexpr auto EVENT_DATA = R"( + + )"; + + constexpr auto PAN_DATA = R"( + + )"; + + constexpr auto MOVE_DATA = R"( + + )"; + + constexpr auto ROTATE_DATA = R"( + + )"; + + constexpr auto SCALE_DATA = R"( + + )"; + + constexpr auto CROP_DATA = R"( + + )"; + + constexpr auto DRAW_DATA = R"( + + )"; + + constexpr auto ERASE_DATA = R"( + + )"; + + constexpr auto COLOR_PICKER_DATA = R"( + + )"; + + constexpr auto UNDO_DATA = R"( + + )"; + + constexpr auto REDO_DATA = R"( + + )"; + + constexpr auto TARGET_DATA = R"( + + )"; + + constexpr auto TARGET_ALT_DATA = R"( + + )"; + + constexpr auto INTERPOLATED_DATA = R"( + + )"; + + constexpr auto UNINTERPOLATED_DATA = R"( + + )"; + + constexpr auto PIVOT_DATA = R"( + + )"; + + constexpr auto TRIGGER_DATA = R"( + + )"; + + constexpr auto PLAYHEAD_DATA = R"( + + )"; + +#define SVG_LIST \ + X(NONE, NONE_DATA, SIZE_SMALL) \ + X(FILE, FILE_DATA, SIZE_NORMAL) \ + X(FOLDER, FOLDER_DATA, SIZE_NORMAL) \ + X(CLOSE, CLOSE_DATA, SIZE_NORMAL) \ + X(ROOT, ROOT_DATA, SIZE_NORMAL) \ + X(LAYER, LAYER_DATA, SIZE_NORMAL) \ + X(NULL_, NULL_DATA, SIZE_NORMAL) \ + X(TRIGGERS, TRIGGERS_DATA, SIZE_NORMAL) \ + X(VISIBLE, VISIBLE_DATA, SIZE_NORMAL) \ + X(INVISIBLE, INVISIBLE_DATA, SIZE_NORMAL) \ + X(SHOW_RECT, SHOW_RECT_DATA, SIZE_NORMAL) \ + X(HIDE_RECT, HIDE_RECT_DATA, SIZE_NORMAL) \ + X(SHOW_UNUSED, SHOW_UNUSED_DATA, SIZE_NORMAL) \ + X(HIDE_UNUSED, HIDE_UNUSED_DATA, SIZE_NORMAL) \ + X(SHOW_LAYERS, SHOW_LAYERS_DATA, SIZE_NORMAL) \ + X(HIDE_LAYERS, HIDE_LAYERS_DATA, SIZE_NORMAL) \ + X(PAN, PAN_DATA, SIZE_NORMAL) \ + X(MOVE, MOVE_DATA, SIZE_NORMAL) \ + X(ROTATE, ROTATE_DATA, SIZE_NORMAL) \ + X(SCALE, SCALE_DATA, SIZE_NORMAL) \ + X(CROP, CROP_DATA, SIZE_NORMAL) \ + X(DRAW, DRAW_DATA, SIZE_NORMAL) \ + X(ERASE, ERASE_DATA, SIZE_NORMAL) \ + X(COLOR_PICKER, COLOR_PICKER_DATA, SIZE_NORMAL) \ + X(UNDO, UNDO_DATA, SIZE_NORMAL) \ + X(REDO, REDO_DATA, SIZE_NORMAL) \ + X(ANIMATION, ANIMATION_DATA, SIZE_NORMAL) \ + X(SPRITESHEET, SPRITESHEET_DATA, SIZE_NORMAL) \ + X(EVENT, EVENT_DATA, SIZE_NORMAL) \ + X(INTERPOLATED, INTERPOLATED_DATA, SIZE_NORMAL) \ + X(UNINTERPOLATED, UNINTERPOLATED_DATA, SIZE_NORMAL) \ + X(TRIGGER, TRIGGER_DATA, SIZE_NORMAL) \ + X(PLAYHEAD, PLAYHEAD_DATA, SIZE_NORMAL) \ + X(PIVOT, PIVOT_DATA, SIZE_NORMAL) \ + X(POINT, UNINTERPOLATED_DATA, SIZE_NORMAL) \ + X(TARGET, TARGET_DATA, SIZE_HUGE) \ + X(TARGET_ALT, TARGET_ALT_DATA, SIZE_HUGE) + + enum Type + { +#define X(name, data, size) name, + SVG_LIST +#undef X + COUNT + }; + + struct Info + { + const char* data{}; + size_t length{}; + glm::ivec2 size{}; + }; + + const Info ICONS[COUNT] = { +#define X(name, data, size) {data, std::strlen(data) - 1, size}, + SVG_LIST +#undef X + }; + + constexpr uint8_t PROGRAM[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb9, 0x55, 0x00, 0x00, 0x00, 0x09, 0x70, + 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, + 0x8b, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd7, 0x3d, 0x0e, 0x80, 0x20, 0x0c, 0x86, 0x61, 0x7b, 0x53, 0x3c, + 0x99, 0xbd, 0x69, 0x1d, 0x8c, 0x83, 0x4d, 0xd0, 0x44, 0x29, 0x7f, 0xbe, 0x5d, 0x08, 0x30, 0xf4, 0x19, 0x80, 0x2f, + 0xc8, 0xd2, 0xb8, 0x04, 0xc0, 0xb4, 0x80, 0x64, 0xc7, 0xb8, 0xf9, 0x86, 0x02, 0x60, 0x36, 0x80, 0xd9, 0x75, 0xbe, + 0xba, 0x7d, 0x00, 0xf3, 0x00, 0x72, 0x8d, 0x7c, 0x83, 0x73, 0x5d, 0xa5, 0xf0, 0x43, 0x04, 0xa0, 0x1a, 0x20, 0xaa, + 0x11, 0x80, 0xf1, 0x01, 0x1a, 0x14, 0x5b, 0x00, 0xfa, 0x03, 0x24, 0xbb, 0x0f, 0x93, 0xa7, 0xb0, 0xf9, 0x1c, 0x46, + 0x00, 0x00, 0x00, 0xe8, 0x06, 0xa0, 0xa5, 0x3f, 0x2a, 0x99, 0x07, 0x0d, 0x40, 0xbf, 0x80, 0xa8, 0x02, 0x30, 0x0e, + 0x40, 0xdf, 0x1e, 0xb2, 0x56, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x07, 0x90, 0x86, 0xff, 0x05, 0xd4, + 0x2e, 0x00, 0x00, 0x00, 0x34, 0x07, 0xec, 0x94, 0x51, 0xac, 0x41, 0x55, 0x6e, 0xe4, 0x26, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; +} \ No newline at end of file diff --git a/src/resource/shader.cpp b/src/resource/shader.cpp new file mode 100644 index 0000000..ba1e234 --- /dev/null +++ b/src/resource/shader.cpp @@ -0,0 +1,72 @@ +#include "shader.h" + +#include "log.h" + +namespace anm2ed::resource +{ + Shader::Shader() = default; + + Shader::Shader(const char* vertex, const char* fragment) + { + id = glCreateProgram(); + + auto compile = [&](const GLuint& id, const char* text) + { + int isCompile{}; + glShaderSource(id, 1, &text, nullptr); + glCompileShader(id); + glGetShaderiv(id, GL_COMPILE_STATUS, &isCompile); + + if (!isCompile) + { + std::string compileLog(255, '\0'); + glGetShaderInfoLog(id, 255, nullptr, compileLog.data()); + logger.error(std::format("Unable to compile shader {}: {}", id, compileLog.c_str())); + return false; + } + return true; + }; + + auto vertexHandle = glCreateShader(GL_VERTEX_SHADER); + auto fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); + + if (!(compile(vertexHandle, vertex) && compile(fragmentHandle, fragment))) return; + + glAttachShader(id, vertexHandle); + glAttachShader(id, fragmentHandle); + + glLinkProgram(id); + + auto isLinked = GL_FALSE; + glGetProgramiv(id, GL_LINK_STATUS, &isLinked); + if (!isLinked) + { + glDeleteProgram(id); + id = 0; + } + + glDeleteShader(vertexHandle); + glDeleteShader(fragmentHandle); + } + + Shader& Shader::operator=(Shader&& other) noexcept + { + if (this != &other) + { + if (is_valid()) glDeleteProgram(id); + id = other.id; + other.id = 0; + } + return *this; + } + + Shader::~Shader() + { + if (is_valid()) glDeleteProgram(id); + } + + bool Shader::is_valid() const + { + return id != 0; + } +} diff --git a/src/resource/shader.h b/src/resource/shader.h new file mode 100644 index 0000000..9794080 --- /dev/null +++ b/src/resource/shader.h @@ -0,0 +1,235 @@ +#pragma once + +#include + +namespace anm2ed::resource::shader +{ + struct Info + { + const char* vertex; + const char* fragment; + }; + + constexpr auto VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; + layout (location = 1) in vec2 i_uv; + out vec2 i_uv_out; + uniform mat4 u_transform; + void main() + { + i_uv_out = i_uv; + gl_Position = u_transform * vec4(i_position, 0.0, 1.0); + } + )"; + + constexpr auto AXIS_VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; // full screen line segment: -1..1 + uniform vec2 u_origin_ndc; // world origin in NDC + uniform int u_axis; // 0 = X axis, 1 = Y axis + + void main() + { + vec2 pos = (u_axis == 0) + ? vec2(i_position.x, u_origin_ndc.y) // horizontal line across screen + : vec2(u_origin_ndc.x, i_position.x); // vertical line across screen; + + gl_Position = vec4(pos, 0.0, 1.0); + } + )"; + + constexpr auto FRAGMENT = R"( + #version 330 core + out vec4 o_fragColor; + uniform vec4 u_color; + void main() + { + o_fragColor = u_color; + } + )"; + + constexpr auto TEXTURE_FRAGMENT = R"( + #version 330 core + in vec2 i_uv_out; + uniform sampler2D u_texture; + uniform vec4 u_tint; + uniform vec3 u_color_offset; + out vec4 o_fragColor; + void main() + { + vec4 texColor = texture(u_texture, i_uv_out); + texColor *= u_tint; + texColor.rgb += u_color_offset; + o_fragColor = texColor; + } + )"; + + constexpr auto GRID_VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; + layout (location = 1) in vec2 i_uv; + + out vec2 i_uv_out; + + void main() + { + i_uv_out = i_position; + gl_Position = vec4(i_position, 0.0, 1.0); + } + )"; + + constexpr auto GRID_FRAGMENT = R"( + #version 330 core + in vec2 i_uv_out; + + uniform mat4 u_transform; + uniform vec2 u_size; + uniform vec2 u_offset; + uniform vec4 u_color; + + out vec4 o_fragColor; + + void main() + { + vec4 world4 = u_transform * vec4(i_uv_out, 0.0, 1.0); + vec2 world = world4.xy / world4.w; + + vec2 cell = max(u_size, vec2(1.0)); + vec2 grid = (world - u_offset) / cell; + + vec2 frac = fract(grid); + vec2 distToLine = min(frac, 1.0 - frac); + float distance = min(distToLine.x, distToLine.y); + + float fw = min(fwidth(grid.x), fwidth(grid.y)); + float alpha = 1.0 - smoothstep(0.0, fw, distance); + + if (alpha <= 0.0) + discard; + + o_fragColor = vec4(u_color.rgb, u_color.a * alpha); + } + )"; + + constexpr auto DASHED_VERTEX = R"( + #version 330 core + layout (location = 0) in vec2 i_position; + + out vec2 v_local; + + uniform mat4 u_transform; + + void main() + { + v_local = i_position; + gl_Position = u_transform * vec4(i_position, 0.0, 1.0); + } + )"; + + constexpr auto DASHED_FRAGMENT = R"( + #version 330 core + in vec2 v_local; + + uniform vec4 u_color; + uniform vec2 u_axis_x; + uniform vec2 u_axis_y; + uniform float u_dash_length; + uniform float u_dash_gap; + uniform float u_dash_offset; + + out vec4 o_fragColor; + + void main() + { + vec2 local = clamp(v_local, 0.0, 1.0); + + float lengthX = max(length(u_axis_x), 1e-4); + float lengthY = max(length(u_axis_y), 1e-4); + + float dash = max(u_dash_length, 1e-4); + float gap = max(u_dash_gap, 0.0); + float period = max(dash + gap, 1e-4); + + vec2 pixel = max(fwidth(v_local), vec2(1e-5)); + + float bottomMask = 1.0 - smoothstep(pixel.y, pixel.y * 2.0, local.y); + float topMask = 1.0 - smoothstep(pixel.y, pixel.y * 2.0, 1.0 - local.y); + float leftMask = 1.0 - smoothstep(pixel.x, pixel.x * 2.0, local.x); + float rightMask = 1.0 - smoothstep(pixel.x, pixel.x * 2.0, 1.0 - local.x); + + float perimeterOffset = u_dash_offset; + + float bottomPos = mod(perimeterOffset + local.x * lengthX, period); + if (bottomPos < 0.0) bottomPos += period; + float bottomDash = bottomMask * (bottomPos <= dash ? 1.0 : 0.0); + + float rightPos = mod(perimeterOffset + lengthX + local.y * lengthY, period); + if (rightPos < 0.0) rightPos += period; + float rightDash = rightMask * (rightPos <= dash ? 1.0 : 0.0); + + float topPos = mod(perimeterOffset + lengthX + lengthY + (1.0 - local.x) * lengthX, period); + if (topPos < 0.0) topPos += period; + float topDash = topMask * (topPos <= dash ? 1.0 : 0.0); + + float leftPos = mod(perimeterOffset + 2.0 * lengthX + lengthY + (1.0 - local.y) * lengthY, period); + if (leftPos < 0.0) leftPos += period; + float leftDash = leftMask * (leftPos <= dash ? 1.0 : 0.0); + + float alpha = max(max(bottomDash, topDash), max(leftDash, rightDash)); + + if (alpha <= 0.0) + discard; + + o_fragColor = vec4(u_color.rgb, u_color.a * alpha); + } + )"; + + constexpr auto UNIFORM_AXIS = "u_axis"; + constexpr auto UNIFORM_COLOR = "u_color"; + constexpr auto UNIFORM_TRANSFORM = "u_transform"; + constexpr auto UNIFORM_TINT = "u_tint"; + constexpr auto UNIFORM_COLOR_OFFSET = "u_color_offset"; + constexpr auto UNIFORM_OFFSET = "u_offset"; + constexpr auto UNIFORM_ORIGIN_NDC = "u_origin_ndc"; + constexpr auto UNIFORM_SIZE = "u_size"; + constexpr auto UNIFORM_MODEL = "u_model"; + constexpr auto UNIFORM_RECT_SIZE = "u_rect_size"; + constexpr auto UNIFORM_TEXTURE = "u_texture"; + constexpr auto UNIFORM_AXIS_X = "u_axis_x"; + constexpr auto UNIFORM_AXIS_Y = "u_axis_y"; + constexpr auto UNIFORM_DASH_LENGTH = "u_dash_length"; + constexpr auto UNIFORM_DASH_GAP = "u_dash_gap"; + constexpr auto UNIFORM_DASH_OFFSET = "u_dash_offset"; + + enum ShaderType + { + LINE, + DASHED, + TEXTURE, + AXIS, + GRID, + COUNT + }; + + const Info SHADERS[COUNT] = {{VERTEX, FRAGMENT}, + {DASHED_VERTEX, DASHED_FRAGMENT}, + {VERTEX, TEXTURE_FRAGMENT}, + {AXIS_VERTEX, FRAGMENT}, + {GRID_VERTEX, GRID_FRAGMENT}}; +} + +namespace anm2ed::resource +{ + class Shader + { + public: + GLuint id{}; + + Shader(); + Shader(const char*, const char*); + Shader& operator=(Shader&&) noexcept; + ~Shader(); + bool is_valid() const; + }; +} diff --git a/src/resource/texture.cpp b/src/resource/texture.cpp new file mode 100644 index 0000000..fc75619 --- /dev/null +++ b/src/resource/texture.cpp @@ -0,0 +1,185 @@ +#include "texture.h" + +#include +#include +#include + +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" + #pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#define STBI_ONLY_PNG +#define STB_IMAGE_IMPLEMENTATION +#include +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include + +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic pop +#endif + +#include "math_.h" + +using namespace anm2ed::resource::texture; +using namespace anm2ed::util::math; +using namespace glm; + +namespace anm2ed::resource +{ + bool Texture::is_valid() { return id != 0; } + + size_t Texture::pixel_size_get() { return size.x * size.y * CHANNELS; } + + void Texture::upload(const uint8_t* data) + { + if (!data || size.x <= 0 || size.y <= 0) return; + + if (!is_valid()) glGenTextures(1, &id); + + pixels.assign(data, data + pixel_size_get()); + + glBindTexture(GL_TEXTURE_2D, id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + glGenerateMipmap(GL_TEXTURE_2D); + + glBindTexture(GL_TEXTURE_2D, 0); + } + + Texture::Texture() = default; + + Texture::~Texture() + { + if (is_valid()) glDeleteTextures(1, &id); + } + + Texture::Texture(const Texture& other) { *this = other; } + + Texture::Texture(Texture&& other) { *this = std::move(other); } + + Texture& Texture::operator=(const Texture& other) // Copy + { + if (this != &other) + { + if (is_valid()) glDeleteTextures(1, &id); + size = other.size; + filter = other.filter; + channels = other.channels; + pixels = other.pixels; + upload(pixels.data()); + } + return *this; + } + + Texture& Texture::operator=(Texture&& other) // Move + { + if (this != &other) + { + if (is_valid()) glDeleteTextures(1, &id); + id = other.id; + size = other.size; + filter = other.filter; + channels = other.channels; + pixels = std::move(other.pixels); + other.id = 0; + } + return *this; + } + + Texture::Texture(const char* svgData, size_t svgDataLength, ivec2 svgSize) + { + if (!svgData) return; + + const std::unique_ptr document = lunasvg::Document::loadFromData(svgData, svgDataLength); + if (!document) return; + + const lunasvg::Bitmap bitmap = document->renderToBitmap(svgSize.x, svgSize.y, 0); + if (bitmap.width() == 0 || bitmap.height() == 0) return; + + size = svgSize; + filter = GL_LINEAR; + upload(bitmap.data()); + } + + Texture::Texture(const uint8_t* data, ivec2 size) + { + this->size = size; + upload(data); + } + + Texture::Texture(const std::string& pngPath) + { + if (const uint8_t* data = stbi_load(pngPath.c_str(), &size.x, &size.y, nullptr, CHANNELS); data) + { + upload(data); + stbi_image_free((void*)data); + } + } + + bool Texture::write_png(const std::string& path) + { + return stbi_write_png(path.c_str(), size.x, size.y, CHANNELS, this->pixels.data(), size.x * CHANNELS); + } + + void Texture::pixel_set(ivec2 position, vec4 color) + { + if (position.x < 0 || position.y < 0 || position.x >= size.x || position.y >= size.y) return; + + uint8 rgba8[4] = {(uint8)float_to_uint8(color.r), (uint8)float_to_uint8(color.g), (uint8)float_to_uint8(color.b), + (uint8)float_to_uint8(color.a)}; + + if (is_valid()) + { + glBindTexture(GL_TEXTURE_2D, id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); + glBindTexture(GL_TEXTURE_2D, 0); + } + + if (pixels.size() == pixel_size_get()) + { + size_t idx = (position.y * size.x + position.x) * CHANNELS; + memcpy(&pixels[idx], rgba8, 4); + } + } + + void Texture::pixel_line(ivec2 start, ivec2 end, vec4 color) + { + auto plot = [&](ivec2 pos) { pixel_set(pos, color); }; + + int x0 = start.x; + int y0 = start.y; + int x1 = end.x; + int y1 = end.y; + + int dx = std::abs(x1 - x0); + int dy = -std::abs(y1 - y0); + int sx = x0 < x1 ? 1 : -1; + int sy = y0 < y1 ? 1 : -1; + int err = dx + dy; + + while (true) + { + plot({x0, y0}); + if (x0 == x1 && y0 == y1) break; + int e2 = 2 * err; + if (e2 >= dy) + { + err += dy; + x0 += sx; + } + if (e2 <= dx) + { + err += dx; + y0 += sy; + } + } + } +} diff --git a/src/resource/texture.h b/src/resource/texture.h new file mode 100644 index 0000000..87d9894 --- /dev/null +++ b/src/resource/texture.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include +#include + +namespace anm2ed::resource::texture +{ + constexpr auto CHANNELS = 4; +} + +namespace anm2ed::resource +{ + class Texture + { + public: + GLuint id{}; + glm::ivec2 size{}; + GLint filter = GL_NEAREST; + int channels{}; + std::vector pixels{}; + + bool is_valid(); + size_t pixel_size_get(); + void upload(); + void upload(const uint8_t*); + + Texture(); + ~Texture(); + Texture(const Texture&); + Texture(Texture&&); + Texture& operator=(const Texture&); + Texture& operator=(Texture&&); + Texture(const uint8_t*, glm::ivec2); + Texture(const char*, size_t, glm::ivec2); + Texture(const std::string&); + bool write_png(const std::string&); + void pixel_set(glm::ivec2, glm::vec4); + void pixel_line(glm::ivec2, glm::ivec2, glm::vec4); + }; +} diff --git a/src/resource/xm_music.h b/src/resource/xm_music.h new file mode 100644 index 0000000..9de74a0 --- /dev/null +++ b/src/resource/xm_music.h @@ -0,0 +1,1744 @@ +#pragma once + +#include +#include + +namespace anm2ed::resource::xm +{ + // Drozerix - Keygen Wraith + // https://modarchive.org/module.php?207854 + // Licensed under the Public Domain license (https://creativecommons.org/licenses/publicdomain/) + // .::~~Dr0ZERiX~~::. + // . . + // . Keygen Wraith . + // ----------------- + // + // A specter now + // for many years... + // ------------------2024 + // Drozerix_gmail.com + constexpr uint8_t ABOUT[] = { + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x3a, 0x20, 0x4b, 0x65, + 0x79, 0x67, 0x65, 0x6e, 0x20, 0x57, 0x72, 0x61, 0x69, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, + 0x4d, 0x69, 0x6c, 0x6b, 0x79, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x31, 0x2e, 0x30, 0x32, 0x2e, 0x30, + 0x30, 0x04, 0x01, 0x14, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x01, 0x00, + 0x07, 0x00, 0xf0, 0x00, 0x08, 0x0d, 0x00, 0x01, 0x04, 0x03, 0x05, 0x09, 0x0a, 0x0b, 0x0c, 0x01, 0x04, 0x03, 0x05, + 0x06, 0x02, 0x0e, 0x07, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x14, 0x03, 0x87, 0x33, 0x02, 0x20, 0x95, 0x33, 0x30, 0x37, 0x1b, 0x09, 0x50, 0x04, 0xa1, 0x83, 0x33, 0x07, + 0x80, 0x83, 0x25, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x30, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x06, 0x01, 0x87, + 0x1b, 0x09, 0x30, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x35, 0x05, 0x80, 0x94, + 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x22, 0x0c, 0x04, 0x80, 0x80, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x27, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x1e, 0x0c, + 0x04, 0x80, 0x80, 0x83, 0x46, 0x04, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x80, 0x94, + 0x81, 0x37, 0x8b, 0x1d, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1e, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x19, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x1d, 0x87, 0x2c, 0x05, 0x30, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x1b, 0x09, 0x04, 0x80, 0x80, + 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x19, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x94, + 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x1b, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x98, 0x01, 0x08, + 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x98, 0x02, 0x08, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, + 0x37, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x09, 0x04, 0x80, 0x80, 0x83, + 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, + 0x80, 0x9b, 0x3d, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x27, 0x88, 0x1b, 0x80, + 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x1b, 0x09, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, + 0x1b, 0x80, 0x87, 0x35, 0x02, 0x20, 0x22, 0x06, 0x18, 0x01, 0x04, 0x8b, 0x1d, 0x0c, 0x04, 0x83, 0x35, 0x07, 0x80, + 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, + 0x20, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, + 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x24, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x29, 0x09, 0x04, 0x80, 0x80, 0x83, 0x41, + 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x20, + 0x09, 0x04, 0x80, 0x80, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, 0x29, 0x80, 0x84, + 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x20, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x1d, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x8c, + 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, 0x22, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x8b, 0x1b, 0x0c, 0x04, 0x80, + 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, 0x84, 0x91, + 0x8c, 0x91, 0x01, 0x8b, 0x1d, 0x09, 0x04, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x81, + 0x1b, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x8c, 0x91, 0x01, 0x88, + 0x04, 0x88, 0x06, 0x81, 0x1d, 0x80, 0x84, 0x91, 0x8c, 0x91, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, + 0x8c, 0x91, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x88, 0x04, 0x80, 0x80, 0x83, + 0x46, 0x05, 0x80, 0x8c, 0x82, 0x01, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x9b, 0x46, + 0x09, 0x02, 0x10, 0x83, 0x35, 0x07, 0x80, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x82, 0x01, 0x9c, 0x61, 0x02, 0x12, 0x88, + 0x04, 0x80, 0x83, 0x49, 0x04, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x9c, 0x61, 0x02, 0x12, 0x80, 0x80, 0x83, 0x49, 0x04, + 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, 0x06, 0x46, 0x09, 0x20, 0x02, 0x10, 0x80, 0x84, 0x91, 0x8c, 0x82, + 0x01, 0x8c, 0x61, 0x02, 0x80, 0x98, 0x02, 0x12, 0x83, 0x49, 0x04, 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, + 0x04, 0x98, 0x02, 0x12, 0x80, 0x84, 0x91, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x80, 0x88, 0x02, 0x83, 0x49, 0x04, + 0x80, 0x8c, 0x82, 0x01, 0x8c, 0x61, 0x02, 0x88, 0x06, 0x88, 0x02, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x52, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, + 0x0a, 0x80, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, + 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x0c, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, + 0x83, 0x3d, 0x09, 0x80, 0x98, 0x04, 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x83, 0x3c, 0x09, 0x88, 0x04, 0x87, 0x3a, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x09, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, + 0x83, 0x38, 0x09, 0x88, 0x06, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, + 0x80, 0x87, 0x3c, 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x87, 0x3a, 0x09, + 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x87, 0x38, + 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, + 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x80, 0x98, 0x01, 0x08, + 0x81, 0x31, 0x80, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x33, 0x0b, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x31, 0x0c, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x0c, 0x83, 0x3a, 0x07, 0x98, 0x04, + 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x2c, 0x0b, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, 0x0c, 0x30, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0b, 0x03, 0x20, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, 0x88, + 0x03, 0x88, 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x09, 0x80, + 0x80, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x03, 0x20, 0x80, 0x9b, 0x3a, 0x02, 0x0a, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0a, 0x83, 0x3a, 0x07, 0x88, 0x03, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x04, 0x87, 0x30, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x85, 0x3d, 0x18, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x2e, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x04, 0xa4, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x29, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x98, 0x04, 0xa2, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2c, 0x09, 0x80, 0x98, + 0x04, 0xa8, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x29, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x31, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2c, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x09, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x31, 0x09, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0a, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x80, 0x98, 0x04, 0xa8, 0x81, 0x3d, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x2c, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, + 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x98, 0x04, 0xa1, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, + 0x08, 0x18, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x0b, 0x80, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x06, 0x04, 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0b, 0x04, + 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, + 0x80, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, + 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, + 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, + 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, + 0x0b, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x37, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, + 0x0c, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, + 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x29, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, + 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, + 0x2e, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x9c, 0x20, + 0x06, 0x01, 0x98, 0x06, 0x10, 0x29, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x9b, + 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, + 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x30, 0x09, 0x04, + 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x98, + 0x06, 0x20, 0x31, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9b, 0x2c, 0x09, 0x04, + 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x30, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2c, 0x09, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, + 0x20, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, + 0x94, 0x30, 0x37, 0x9b, 0x2c, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, + 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, + 0x47, 0x9b, 0x2e, 0x0c, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x2c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x9b, 0x35, + 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, + 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, + 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x35, 0x0a, + 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, + 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, + 0x47, 0x9b, 0x33, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x33, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, + 0x97, 0x38, 0x0c, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, + 0x80, 0x84, 0x81, 0x97, 0x38, 0x0c, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, + 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, + 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, + 0x01, 0x98, 0x06, 0x10, 0x31, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x98, 0x04, + 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, + 0x38, 0x0a, 0x30, 0x47, 0x9b, 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, + 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x30, + 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x09, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x49, 0x04, 0x20, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xaf, 0x03, + 0x9b, 0x36, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x36, 0x0a, 0x83, + 0x36, 0x07, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2e, 0x0b, 0x83, 0x2a, 0x07, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, + 0x04, 0xa3, 0x88, 0x04, 0x87, 0x36, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa6, + 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x87, 0x2e, 0x0b, 0x30, 0x80, + 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x31, 0x0c, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa3, 0x83, 0x49, 0x04, 0x80, 0x80, + 0x80, 0x88, 0x04, 0x98, 0x04, 0xa6, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x36, 0x0b, 0x83, 0x2a, + 0x07, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, + 0x3d, 0x01, 0x83, 0x3a, 0x0a, 0x83, 0x36, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, + 0x04, 0x87, 0x36, 0x0b, 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3d, + 0x09, 0x83, 0x36, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa4, 0x88, 0x06, 0x87, 0x3a, 0x0a, + 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3c, 0x0a, 0x83, 0x2a, 0x07, 0x98, 0x04, 0xa6, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, + 0x3a, 0x0b, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa4, 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x3c, + 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x9b, 0x36, 0x0b, 0x03, 0x10, 0x83, 0x2a, 0x07, 0x80, 0x81, + 0x3d, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x04, 0x87, 0x3a, 0x0b, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x01, 0x08, 0x83, 0x2a, 0x07, 0x98, 0x04, 0xa2, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x02, 0x08, 0x88, + 0x06, 0x36, 0x0b, 0x30, 0x03, 0x10, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x83, 0x36, 0x07, 0x88, + 0x03, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x98, 0x01, 0x08, 0x80, 0x82, 0x03, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x2a, 0x07, 0x98, 0x02, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, + 0xa4, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3c, 0x0c, 0x83, 0x36, + 0x07, 0x98, 0x04, 0xa3, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x83, 0x36, 0x07, 0x98, 0x04, 0xa4, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x88, 0x04, + 0x88, 0x06, 0x87, 0x3c, 0x0c, 0x30, 0x80, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, + 0x2c, 0x07, 0x88, 0x04, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x38, 0x0a, 0x83, 0x38, 0x07, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3c, 0x0b, 0x83, 0x2c, 0x07, 0x80, + 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x84, 0x14, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x3f, 0x0a, 0x83, 0x2c, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x84, 0x14, 0x88, + 0x06, 0x87, 0x3c, 0x0b, 0x30, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0c, 0x83, 0x38, 0x07, 0x84, 0x10, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x04, 0x87, 0x3f, 0x0a, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x3c, 0x0a, 0x83, 0x2c, 0x07, 0x84, 0x10, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x3d, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x38, 0x09, 0x83, 0x38, 0x07, 0x98, 0x04, 0xa2, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x3c, 0x0a, 0x30, 0x9d, 0x3d, 0x24, 0x02, + 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x38, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x2c, 0x09, 0x83, 0x2c, 0x07, 0x98, 0x04, 0xa3, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x30, 0x0a, 0x88, 0x04, 0x98, + 0x04, 0xa3, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0b, 0x83, 0x38, 0x07, 0x98, 0x04, 0xa3, 0x81, + 0x31, 0x80, 0x80, 0x83, 0x30, 0x0c, 0x88, 0x06, 0x87, 0x2c, 0x09, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, + 0x83, 0x33, 0x0b, 0x83, 0x2c, 0x07, 0x87, 0x30, 0x0a, 0x30, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x30, 0x09, 0x88, + 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x33, 0x0a, 0x83, 0x2c, 0x07, + 0x87, 0x30, 0x0c, 0x30, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x38, 0x0b, 0x88, 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, + 0x82, 0x03, 0x83, 0x3d, 0x08, 0x83, 0x33, 0x0c, 0x83, 0x38, 0x07, 0x87, 0x30, 0x09, 0x30, 0x83, 0x49, 0x04, 0x80, + 0x80, 0x83, 0x38, 0x0b, 0x88, 0x04, 0x87, 0x33, 0x0a, 0x30, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x09, 0x83, 0x2c, 0x07, 0x87, 0x38, 0x0b, 0x30, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x3d, 0x0a, 0x88, 0x06, + 0x87, 0x33, 0x0c, 0x30, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3f, 0x0b, 0x83, 0x38, 0x07, 0x87, 0x38, + 0x0b, 0x30, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa5, 0x88, 0x04, 0x87, 0x3c, 0x09, 0x30, 0x80, 0x8a, + 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa5, 0x83, 0x38, 0x07, 0x87, 0x3d, 0x0a, 0x30, 0x81, 0x4b, 0x88, + 0x0a, 0x80, 0x98, 0x04, 0xa5, 0x88, 0x06, 0x87, 0x3f, 0x0b, 0x30, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x52, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, + 0x0a, 0x80, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, + 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x0c, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, + 0x83, 0x3d, 0x09, 0x80, 0x98, 0x04, 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x83, 0x3c, 0x09, 0x88, 0x04, 0x87, 0x3a, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, 0x09, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, + 0x83, 0x38, 0x09, 0x88, 0x06, 0x87, 0x3d, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3a, 0x09, + 0x80, 0x87, 0x3c, 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x87, 0x3a, 0x09, + 0x30, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x87, 0x38, + 0x09, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x87, 0x3a, 0x09, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, + 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x80, 0x98, 0x01, 0x08, + 0x81, 0x31, 0x80, 0x80, 0x80, 0x88, 0x06, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, + 0x33, 0x0b, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa6, 0x88, 0x04, 0x87, 0x35, 0x0a, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x31, 0x0c, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x06, 0x87, 0x33, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x0c, 0x83, 0x3a, 0x07, 0x98, 0x04, + 0xa6, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x31, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x2c, 0x0b, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, 0x0c, 0x30, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0b, 0x03, 0x20, 0x80, 0x80, 0x80, 0x88, 0x0a, 0x80, 0x88, + 0x03, 0x88, 0x04, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x09, 0x80, + 0x80, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x03, 0x20, 0x80, 0x9b, 0x3a, 0x02, 0x0a, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0a, 0x83, 0x3a, 0x07, 0x88, 0x03, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, + 0x04, 0x87, 0x30, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x85, 0x3d, 0x18, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa2, 0x88, 0x06, 0x87, 0x2e, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x04, 0xa4, 0x80, 0x80, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x29, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x98, 0x04, 0xa2, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2c, 0x09, 0x80, 0x98, + 0x04, 0xa8, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x29, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x31, 0x09, 0x80, 0x98, 0x04, 0xa2, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2c, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x30, 0x09, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x31, 0x09, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0a, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x30, + 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x80, 0x98, 0x04, 0xa8, 0x81, 0x3d, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x2c, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, + 0x81, 0x31, 0x80, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x98, 0x04, 0xa1, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x82, 0x02, 0x87, 0x3d, + 0x08, 0x18, 0x83, 0x38, 0x09, 0x80, 0x98, 0x01, 0x08, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, + 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x3d, 0x0a, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3c, + 0x0b, 0x80, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3d, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0xee, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x46, 0x0c, 0x83, 0x3a, + 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x41, 0x0c, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x83, 0x44, 0x0c, 0x83, 0x2e, 0x07, 0x80, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x83, 0x3f, + 0x0c, 0x98, 0x06, 0x01, 0x87, 0x46, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x41, 0x0c, 0x83, + 0x3a, 0x07, 0x87, 0x41, 0x0c, 0x30, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x83, 0x3d, 0x0c, 0x88, 0x04, 0x87, 0x44, + 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3f, 0x0c, 0x83, 0x3a, 0x07, 0x87, 0x3f, 0x0c, + 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x9b, 0x3d, 0x0c, 0x04, 0xa1, 0x88, 0x06, 0x87, 0x41, 0x0c, 0x30, 0x80, + 0x82, 0x02, 0x83, 0x3d, 0x08, 0x9b, 0x3c, 0x0b, 0x04, 0xa1, 0x83, 0x2e, 0x07, 0x87, 0x3d, 0x0c, 0x30, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x9b, 0x38, 0x0b, 0x04, 0xa1, 0x88, 0x04, 0x87, 0x3f, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x9b, 0x3a, 0x0b, 0x04, 0xa1, 0x83, 0x3a, 0x07, 0x3d, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x88, 0x0a, + 0x80, 0x9b, 0x38, 0x0b, 0x04, 0xa2, 0x88, 0x06, 0x3c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x01, 0x9b, 0x3a, 0x0a, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x38, 0x0b, 0x30, 0x04, 0xa1, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x9b, 0x35, 0x0a, 0x04, 0xa2, 0x88, 0x04, 0x3a, 0x0b, 0x30, 0x04, 0xa1, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x38, 0x0a, 0x83, 0x2e, 0x07, 0x38, 0x0b, 0x30, 0x04, 0xa2, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x9b, 0x33, 0x0a, 0x04, 0xa3, 0x88, 0x06, 0x3a, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, 0x35, 0x0a, 0x30, 0x04, 0xa2, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x9b, 0x31, 0x09, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x33, 0x09, 0x83, 0x2e, 0x07, 0x33, 0x0a, 0x30, 0x04, 0xa3, 0x81, 0x31, 0x80, 0x80, 0x9b, 0x30, 0x0a, + 0x04, 0xa4, 0x88, 0x06, 0x87, 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2c, 0x0a, 0x83, + 0x3a, 0x07, 0x31, 0x09, 0x30, 0x04, 0xa3, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x9b, 0x31, 0x0a, 0x04, 0xa5, 0x88, 0x04, + 0x87, 0x33, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x0b, 0x83, 0x3a, 0x07, 0x30, + 0x0a, 0x30, 0x04, 0xa4, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x9b, 0x2c, 0x0b, 0x04, 0xa5, 0x88, 0x06, 0x87, 0x2c, 0x0a, + 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x83, 0x2e, 0x07, 0x31, 0x0a, 0x30, 0x04, 0xa5, 0x83, + 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x87, 0x30, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, + 0x83, 0x3a, 0x07, 0x2c, 0x0b, 0x30, 0x04, 0xa5, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, + 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x98, 0x02, 0x08, 0x83, 0x2e, 0x07, 0x80, 0x80, + 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x3a, + 0x0c, 0x83, 0x2e, 0x07, 0x98, 0x01, 0x08, 0x81, 0x31, 0x88, 0x0a, 0x80, 0x83, 0x35, 0x0c, 0x88, 0x06, 0x98, 0x02, + 0x08, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x38, 0x0b, 0x83, 0x3a, 0x07, 0x98, 0x01, 0x08, + 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x83, 0x33, 0x0b, 0x88, 0x04, 0x87, 0x3a, 0x0c, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x83, 0x35, 0x0a, 0x83, 0x2e, 0x07, 0x87, 0x35, 0x0c, 0x30, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, + 0x83, 0x31, 0x0a, 0x88, 0x06, 0x87, 0x38, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x33, 0x09, + 0x83, 0x3a, 0x07, 0x87, 0x33, 0x0b, 0x30, 0x85, 0x3d, 0x1c, 0x88, 0x0a, 0x80, 0x83, 0x31, 0x09, 0x88, 0x04, 0x87, + 0x35, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x30, 0x0a, 0x83, 0x3a, 0x07, 0x87, 0x31, + 0x0a, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x83, 0x2c, 0x0b, 0x88, 0x06, 0x87, 0x33, 0x09, 0x30, 0x80, 0x82, + 0x02, 0x83, 0x3d, 0x08, 0x83, 0x2e, 0x0c, 0x83, 0x2e, 0x07, 0x87, 0x31, 0x09, 0x30, 0x83, 0x49, 0x04, 0x80, 0x80, + 0x80, 0x88, 0x04, 0x87, 0x30, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x83, 0x2c, 0x0c, 0x83, + 0x3a, 0x07, 0x87, 0x2c, 0x0b, 0x30, 0x80, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x2e, 0x0c, 0x30, 0x80, 0x8a, + 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x2e, 0x0b, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, + 0x04, 0xa8, 0x88, 0x04, 0x87, 0x2c, 0x0c, 0x30, 0x9d, 0x3d, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x31, 0x0a, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x84, 0x18, 0x88, 0x06, 0x87, + 0x2e, 0x0b, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x83, 0x35, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x81, 0x3d, + 0x88, 0x0a, 0x80, 0x9c, 0x18, 0x04, 0xa2, 0x88, 0x04, 0x87, 0x31, 0x0a, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x38, 0x0a, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x84, 0x18, 0x81, 0x31, 0x80, 0x80, 0x84, 0x18, 0x88, 0x06, + 0x87, 0x35, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3a, 0x0b, 0x83, 0x3a, 0x07, 0x84, 0x18, + 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x87, 0x38, 0x0a, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x83, 0x3d, 0x0c, 0x83, 0x3a, 0x07, 0x84, 0x18, 0x81, 0x3d, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, + 0x87, 0x3a, 0x0b, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x83, 0x3c, 0x0b, 0x83, 0x2e, 0x07, 0x80, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x98, 0x04, 0xa8, 0x88, 0x04, 0x87, 0x3d, 0x0c, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x83, 0x38, 0x09, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x87, 0x3c, 0x0b, + 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x01, 0x83, 0x3a, 0x0a, 0x83, 0x2e, 0x07, 0x98, 0x04, 0xa8, 0x83, 0x49, + 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, 0x87, 0x38, 0x09, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0xa3, 0x83, 0x2e, 0x07, 0x80, 0x81, 0x4b, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, + 0x87, 0x3a, 0x0a, 0x30, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xc3, 0x03, 0x87, 0x3a, 0x02, 0x30, 0x60, + 0x06, 0x30, 0x02, 0x08, 0x83, 0x3a, 0x0a, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x8c, 0x82, 0x02, + 0x98, 0x04, 0xa3, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x8c, 0x82, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x87, 0x3d, + 0x05, 0x20, 0x84, 0x81, 0x8c, 0x82, 0x02, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x87, 0x3a, 0x0a, 0x30, 0x80, 0x80, + 0x8c, 0x82, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x04, 0xa3, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x8c, 0x82, 0x02, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa3, 0x80, + 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x8c, 0x81, + 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, + 0x06, 0x01, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, + 0x81, 0x02, 0x9b, 0x3d, 0x0a, 0x03, 0x03, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x8c, 0x81, 0x02, + 0x98, 0x03, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x80, 0x8c, 0x81, 0x02, 0x98, 0x03, 0x03, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x03, 0x11, 0x88, 0x06, 0x3d, 0x0a, 0x30, 0x03, + 0x03, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x03, 0xa3, 0x80, 0x98, 0x03, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, + 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x03, 0x03, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x04, + 0xa3, 0x80, 0x98, 0x03, 0x11, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x98, 0x06, + 0x10, 0x98, 0x03, 0xa3, 0x80, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, + 0x05, 0x18, 0x84, 0x81, 0x8c, 0x81, 0x02, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa3, 0x80, 0x84, 0x81, 0x8c, + 0x81, 0x02, 0x98, 0x04, 0xa3, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x8c, 0x81, 0x02, 0x98, + 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa3, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x0b, 0x18, 0x37, 0x98, 0x04, 0x03, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x10, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, + 0xa3, 0x80, 0x84, 0x92, 0x94, 0x18, 0x37, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, + 0x94, 0x10, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0x03, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x09, 0x20, 0x37, + 0x9b, 0x38, 0x0c, 0x0c, 0x20, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x91, 0x94, 0x18, 0x37, 0x98, + 0x06, 0x10, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x92, 0x94, 0x15, 0x37, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x11, 0x37, 0x98, 0x06, 0x10, 0x88, 0x06, 0x38, 0x0c, 0x30, 0x0c, 0x20, 0x80, + 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, 0x47, 0x8b, 0x38, 0x09, 0x04, 0x83, 0x2c, 0x07, 0x98, 0x06, 0x10, + 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x88, 0x04, 0x80, 0x80, 0x94, + 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x10, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, + 0x01, 0x98, 0x06, 0x01, 0x8f, 0x38, 0x09, 0x30, 0x04, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x8b, 0x38, 0x0c, + 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x88, 0x04, 0x80, 0x80, 0x94, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, + 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, + 0x47, 0x9b, 0x33, 0x0a, 0x03, 0x03, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, + 0x98, 0x03, 0x05, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x03, 0x08, 0x80, 0x98, 0x06, 0x01, + 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x03, 0x10, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x03, 0x03, 0x80, 0x80, 0x97, + 0x38, 0x0c, 0x30, 0x47, 0x80, 0x80, 0x98, 0x03, 0x05, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, + 0x01, 0x88, 0x04, 0x98, 0x03, 0x08, 0x80, 0x80, 0x94, 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x03, 0x10, 0x87, 0x3d, + 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x80, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0c, + 0x30, 0x47, 0x8b, 0x30, 0x0b, 0x04, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x10, 0x8f, 0x30, 0x0b, 0x30, 0x04, + 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, + 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x88, 0x04, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, + 0x88, 0x04, 0x80, 0x84, 0x92, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x8b, 0x2c, 0x0c, 0x04, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, 0x84, 0x92, 0x94, 0x24, + 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, + 0x88, 0x06, 0x8f, 0x2c, 0x0c, 0x30, 0x04, 0x80, 0x84, 0x92, 0x97, 0x38, 0x09, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x91, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x84, 0x92, 0x94, 0x30, 0x47, 0x88, 0x04, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x20, + 0x47, 0x90, 0x01, 0x88, 0x06, 0x88, 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x3c, 0x04, 0x87, 0x36, + 0x03, 0x30, 0x97, 0x36, 0x09, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x04, 0xa1, 0x83, 0x2a, 0x07, 0x80, 0x83, 0x3d, 0x05, + 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, + 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x31, + 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x36, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, + 0x30, 0x47, 0x98, 0x04, 0xa4, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x36, 0x0b, 0x30, 0x47, 0x98, 0x04, 0xa4, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa4, + 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa7, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa4, 0x80, 0x80, 0x97, 0x36, 0x0c, 0x30, 0x47, 0x9b, 0x33, 0x0a, 0x03, 0x02, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x03, 0x02, 0x88, 0x04, 0x98, 0x04, + 0xa7, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x03, 0x02, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, + 0x94, 0x22, 0x47, 0x98, 0x03, 0x02, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x03, 0x02, 0x80, 0x84, 0x81, 0x97, 0x36, 0x0c, + 0x30, 0x47, 0x9b, 0x33, 0x0b, 0x04, 0x01, 0x80, 0x98, 0x03, 0x02, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, + 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x98, 0x03, 0x02, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x9c, 0x50, 0x04, 0xa1, + 0x80, 0x98, 0x03, 0x02, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x10, + 0x33, 0x0b, 0x30, 0x04, 0x01, 0x80, 0x84, 0x81, 0x97, 0x36, 0x0b, 0x30, 0x47, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x80, + 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x9c, + 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x9b, 0x31, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x20, 0x2e, 0x0b, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x92, 0x97, 0x36, 0x0a, 0x30, 0x47, 0x9b, 0x36, 0x09, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x31, 0x0c, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x92, 0x94, 0x24, 0x47, 0x9b, 0x3a, 0x0c, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, + 0x84, 0x91, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x36, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, + 0x36, 0x09, 0x30, 0x47, 0x9b, 0x38, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, + 0x91, 0x94, 0x20, 0x47, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x3a, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, + 0x30, 0x47, 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x91, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x38, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, + 0x30, 0x37, 0x9b, 0x3a, 0x0a, 0x04, 0xa1, 0x83, 0x2e, 0x07, 0x9c, 0x10, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, + 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x35, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, + 0x98, 0x06, 0x01, 0x3a, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9c, 0x61, 0x01, 0x08, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x61, 0x02, 0x08, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x61, 0x02, 0x08, 0x88, 0x06, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x80, 0x97, + 0x3a, 0x0b, 0x30, 0x37, 0x9b, 0x35, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x61, 0x02, 0x08, 0x87, 0x3c, 0x05, 0x12, 0x84, + 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x9c, 0x61, 0x01, 0x08, 0x80, 0x80, 0x94, 0x30, 0x37, 0x9b, + 0x31, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x61, 0x02, 0x08, 0x80, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, 0x06, 0x01, + 0x88, 0x06, 0x35, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x31, 0x0b, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x31, 0x0a, + 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x9b, 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, + 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x31, 0x0b, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x9b, 0x31, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, + 0x84, 0x81, 0x94, 0x28, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x30, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, + 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, + 0x22, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x10, 0x31, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, + 0x0b, 0x30, 0x37, 0x9b, 0x30, 0x0a, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, + 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, + 0x9b, 0x27, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x91, 0x94, 0x20, 0x37, + 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x20, 0x30, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x0a, 0x30, + 0x37, 0x9b, 0x29, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x28, 0x37, 0x9c, + 0x20, 0x06, 0x01, 0x88, 0x04, 0x27, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, 0x24, 0x37, 0x9b, 0x2c, 0x0b, + 0x04, 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, 0x91, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, + 0x88, 0x06, 0x29, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0c, 0x04, + 0xa1, 0x80, 0x9c, 0x10, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x2c, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x92, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, + 0x49, 0x04, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2e, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x22, 0x03, 0x87, 0x3a, 0x02, 0x10, 0x95, 0x3a, 0x20, 0x37, 0x98, 0x0f, 0x07, + 0x83, 0x3a, 0x07, 0x98, 0x0f, 0xf0, 0x83, 0x25, 0x05, 0x80, 0x94, 0x18, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, + 0x98, 0x06, 0x01, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x98, 0x04, 0xa2, 0x80, 0x98, 0x04, 0xa2, 0x83, 0x30, 0x05, + 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x98, 0x06, 0x01, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, + 0x80, 0x88, 0x04, 0x83, 0x35, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, + 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, + 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, + 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x88, 0x1b, 0x84, 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, + 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, + 0x80, 0x88, 0x04, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x87, 0x2c, 0x05, + 0x30, 0x84, 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x12, 0x37, 0x88, + 0x06, 0x88, 0x06, 0x88, 0x06, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x36, 0x05, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, + 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, + 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, 0x94, 0x10, 0x37, 0x88, 0x06, + 0x88, 0x04, 0x88, 0x06, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x36, 0x05, 0x80, + 0x94, 0x10, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, 0x06, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, + 0x04, 0x9b, 0x3d, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, 0x88, 0x06, 0x88, 0x04, 0x88, 0x06, 0x88, 0x1b, 0x84, + 0x91, 0x94, 0x14, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x80, 0x94, 0x12, 0x37, 0x88, 0x06, 0x88, 0x06, 0x88, + 0x06, 0x88, 0x1b, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x88, 0x04, 0x80, 0x88, 0x04, 0x3d, 0x04, 0x15, 0x1b, 0xc1, 0x80, + 0x94, 0x18, 0x37, 0x80, 0x88, 0x04, 0x80, 0x9c, 0x10, 0x1b, 0xc2, 0x84, 0x91, 0x94, 0x20, 0x37, 0x80, 0x80, 0x80, + 0x8f, 0x3d, 0x04, 0x15, 0x1b, 0x80, 0x94, 0x18, 0x37, 0x80, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, + 0x87, 0x22, 0x09, 0x10, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x80, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, + 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, + 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x80, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x41, + 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, + 0x80, 0x9b, 0x49, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x80, 0x88, 0x1b, 0x84, 0x91, + 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x80, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, + 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x80, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x12, + 0x37, 0x84, 0x92, 0x88, 0x06, 0x80, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x25, 0x06, 0x20, 0x01, + 0x08, 0x80, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, 0x8c, 0x92, 0x01, 0x80, 0x84, 0x91, 0x94, 0x14, 0x37, + 0x84, 0x92, 0x80, 0x8c, 0x92, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x92, + 0x01, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x92, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x10, + 0x37, 0x84, 0x92, 0x88, 0x04, 0x9c, 0x91, 0x01, 0x10, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, + 0x91, 0x01, 0x83, 0x46, 0x05, 0x80, 0x94, 0x10, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x91, 0x01, 0x80, 0x80, 0x95, + 0x3a, 0x20, 0x37, 0x84, 0x92, 0x80, 0x9c, 0x81, 0x02, 0x08, 0x9b, 0x42, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x18, 0x37, + 0x84, 0x92, 0x88, 0x04, 0x8c, 0x81, 0x02, 0x88, 0x1b, 0x84, 0x91, 0x94, 0x14, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, + 0x02, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x12, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x81, 0x02, 0x80, 0x80, 0x95, 0x3a, + 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, 0x02, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x04, + 0x9c, 0x81, 0x02, 0x20, 0x80, 0x84, 0x91, 0x94, 0x20, 0x37, 0x84, 0x92, 0x80, 0x8c, 0x81, 0x02, 0x83, 0x3a, 0x05, + 0x80, 0x94, 0x18, 0x37, 0x84, 0x92, 0x88, 0x06, 0x8c, 0x81, 0x02, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x8c, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3a, 0x0a, 0x04, 0xa3, 0x83, 0x3a, 0x07, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x06, 0x01, 0x80, 0x80, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, 0x3a, 0x0a, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, + 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x06, 0x80, 0x82, 0x02, 0x83, + 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x06, + 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0a, 0x04, 0xa3, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa1, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0b, 0x04, 0x80, 0x98, 0x01, 0x08, 0x80, 0x88, 0x0a, 0x80, 0x8c, + 0x20, 0x04, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0c, + 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0b, 0x30, + 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0b, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x20, + 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, + 0x8b, 0x3c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, + 0x3d, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0a, 0x04, 0x80, 0x8c, 0x20, + 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, + 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0b, 0x04, 0x83, 0x3a, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, + 0x88, 0x04, 0x8f, 0x38, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0x46, 0x80, 0x88, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, 0x04, 0x48, 0x88, 0x06, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0a, 0x04, 0xa2, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x98, 0x04, 0x46, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa4, 0x80, 0x98, 0x04, 0x48, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa4, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x38, 0x03, + 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x38, 0x09, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0xa8, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, + 0x80, 0x98, 0x04, 0xa8, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x38, 0x09, 0x30, 0x04, 0xa1, + 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x04, 0x88, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, + 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, + 0x08, 0x9b, 0x33, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x98, 0x02, 0x08, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x98, 0x01, 0x08, 0x80, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x33, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, + 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x33, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x0c, 0x04, 0x80, + 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x33, 0x0b, 0x30, 0x04, 0x80, 0x82, + 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x30, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x20, 0x80, 0x80, 0x8c, 0x20, + 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x2c, 0x0b, 0x04, + 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x30, 0x0c, 0x30, 0x04, + 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x14, + 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x2c, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, + 0x8b, 0x30, 0x09, 0x04, 0x83, 0x2c, 0x07, 0x8c, 0x20, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, + 0x04, 0x8f, 0x31, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2e, 0x09, 0x04, 0x80, 0x8c, + 0x20, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x30, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, + 0x83, 0x3d, 0x08, 0x8b, 0x2c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x8f, 0x2e, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2e, 0x0b, 0x04, 0x80, 0x88, + 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x2c, 0x0a, 0x30, 0x04, 0x80, 0x09, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x6d, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0c, 0x04, + 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x80, 0x85, 0x3d, 0x20, 0x88, 0x0a, 0x80, 0x88, 0x04, + 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, + 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, + 0x06, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, + 0x08, 0x88, 0x04, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, + 0x80, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, + 0x35, 0x0a, 0x04, 0xa2, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, + 0x02, 0x08, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x98, 0x01, 0x08, 0x80, + 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x35, 0x0a, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x8b, 0x35, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, + 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x8c, 0x20, + 0x04, 0x85, 0x3d, 0x20, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x35, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0a, 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x09, + 0x04, 0x80, 0x8c, 0x20, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0a, 0x30, + 0x04, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x09, 0x04, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, + 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x09, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x9b, 0x3c, 0x0a, 0x04, 0x46, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x9c, 0x20, 0x04, 0x48, 0x88, 0x06, 0x8f, + 0x3a, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3d, 0x0b, 0x04, 0xa2, 0x80, 0x8c, 0x20, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x3c, 0x0a, 0x30, 0x04, 0x46, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x98, 0x04, 0xa8, 0x80, 0x9c, 0x20, 0x04, 0x48, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, + 0xa8, 0x88, 0x06, 0x3d, 0x0b, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3f, + 0x09, 0x04, 0xa1, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, + 0x04, 0xa8, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x98, 0x04, 0xa8, 0x85, 0x3d, 0x20, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x3f, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x88, 0x04, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x04, 0x80, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x85, 0x3d, 0x14, 0x88, 0x0a, 0x80, + 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x9b, 0x3c, 0x0c, 0x04, 0xa1, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x80, 0x8a, 0x03, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x98, 0x06, 0x01, 0x80, 0x98, 0x01, 0x08, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, + 0x3c, 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x98, 0x06, 0x01, 0x80, 0x8a, + 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x38, 0x0c, 0x03, 0x08, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x03, 0x88, 0x04, 0x88, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x03, 0x80, 0x88, 0x04, 0x85, + 0x3d, 0x20, 0x80, 0x80, 0x88, 0x03, 0x88, 0x06, 0x38, 0x0c, 0x30, 0x03, 0x08, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, + 0x08, 0x88, 0x03, 0x83, 0x2c, 0x07, 0x88, 0x03, 0x85, 0x3d, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x04, 0x88, + 0x03, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x03, 0x80, 0x88, 0x03, 0x85, 0x3d, 0x14, 0x88, 0x0a, + 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x03, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x9b, 0x33, 0x0c, 0x03, 0x10, 0x80, + 0x88, 0x03, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x03, 0x88, 0x04, 0x88, 0x03, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x03, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, 0x06, 0x33, 0x0c, 0x30, 0x03, 0x10, + 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x03, 0x80, 0x88, 0x03, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x03, 0x88, + 0x04, 0x88, 0x03, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x88, 0x03, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x03, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xaf, 0x03, + 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0c, 0x04, 0xa3, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, + 0x06, 0x01, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, 0x35, 0x0c, 0x30, + 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x06, 0x01, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, + 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x06, 0x80, 0x82, 0x02, 0x83, + 0x3d, 0x08, 0x88, 0x06, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x88, 0x06, + 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, + 0x01, 0x08, 0x88, 0x06, 0x88, 0x06, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x35, 0x0c, 0x04, 0xa3, 0x80, + 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x3d, 0x05, 0x24, + 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0b, 0x04, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x35, 0x0c, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x83, + 0x3d, 0x08, 0x8b, 0x31, 0x0a, 0x04, 0x83, 0x3a, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, + 0x04, 0x88, 0x04, 0x8f, 0x31, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x09, 0x04, + 0x80, 0x8c, 0x10, 0x04, 0x83, 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0a, 0x30, 0x04, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x30, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x31, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, + 0x8b, 0x2c, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, + 0x30, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x27, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, + 0x04, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x2c, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x2e, 0x0b, 0x04, 0x46, 0x80, 0x88, 0x04, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x9c, 0x20, 0x04, 0x48, + 0x88, 0x06, 0x8f, 0x27, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x31, 0x0a, 0x04, 0xa2, + 0x80, 0x8c, 0x10, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x2e, 0x0b, 0x30, 0x04, 0x46, 0x80, 0x8a, + 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x9b, 0x3a, 0x09, 0x04, 0xa3, 0x80, 0x9c, 0x10, 0x04, 0x48, 0x83, 0x31, 0x05, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x06, 0x31, 0x0a, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x36, 0x03, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x36, 0x09, 0x04, 0xa1, 0x83, 0x2a, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x04, 0x3a, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, + 0x0a, 0x04, 0x80, 0x98, 0x04, 0xa3, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x36, 0x09, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x36, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x87, 0x3d, + 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x8f, 0x36, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x36, 0x0c, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x31, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, + 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, + 0x36, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3a, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0b, 0x30, 0x04, 0x3d, 0x05, 0x24, 0x02, 0x10, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x09, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, + 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x42, + 0x09, 0x04, 0x83, 0x36, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3d, + 0x09, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, 0x31, + 0x05, 0x80, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x42, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, + 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3d, + 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, + 0x08, 0x8b, 0x3a, 0x0c, 0x04, 0x83, 0x36, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, + 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x36, 0x09, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3a, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, + 0x83, 0x3d, 0x08, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x88, 0x04, + 0x8f, 0x36, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x4b, 0x04, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x88, 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xc9, 0x03, 0x9b, 0x38, 0x03, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x44, 0x09, 0x04, 0xa3, 0x83, 0x2c, 0x07, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x3f, 0x0a, 0x06, 0x01, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, + 0x01, 0x44, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x06, 0x80, 0x88, + 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x3f, 0x0a, 0x30, 0x06, 0x01, 0x80, 0x8a, + 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3f, 0x0c, 0x06, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, 0x30, 0x06, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x44, 0x09, 0x06, + 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x8f, 0x3f, 0x0c, 0x30, 0x06, 0x80, + 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x98, 0x01, + 0x08, 0x88, 0x06, 0x8f, 0x44, 0x09, 0x30, 0x06, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x3f, 0x09, 0x04, + 0xa3, 0x80, 0x98, 0x01, 0x08, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x02, 0x08, 0x3d, + 0x05, 0x24, 0x02, 0x10, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0a, 0x04, 0x80, 0x98, 0x01, 0x08, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x3f, 0x09, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x03, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x04, 0x83, 0x2c, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x3d, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x38, + 0x0c, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, + 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x33, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, + 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, + 0x08, 0x18, 0x8b, 0x38, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x8f, 0x33, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x03, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x09, 0x04, 0x80, 0x88, 0x04, + 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x38, 0x0a, 0x30, 0x04, 0x80, 0x82, 0x03, 0x87, 0x3d, + 0x08, 0x18, 0x98, 0x04, 0x46, 0x80, 0x88, 0x04, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0x48, 0x88, 0x06, + 0x8f, 0x31, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x03, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x30, 0x09, 0x04, 0xa2, 0x80, 0x88, + 0x04, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x98, 0x04, 0x46, 0x80, 0x8a, 0x03, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x9b, 0x2c, 0x0a, 0x04, 0xa3, 0x80, 0x98, 0x04, 0x48, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, + 0x88, 0x06, 0x30, 0x09, 0x30, 0x04, 0xa2, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0b, + 0x04, 0xa3, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x2c, 0x0a, + 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x2c, 0x0c, 0x04, 0x80, 0x98, 0x04, 0xa3, + 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x2e, 0x0b, 0x30, 0x04, 0xa3, 0x80, 0x8a, 0x02, + 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x31, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x8f, 0x2c, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x30, 0x0b, + 0x04, 0x80, 0x88, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x31, 0x0c, 0x30, 0x04, + 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x8b, 0x2e, 0x0a, 0x04, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, 0x80, 0x8c, + 0x20, 0x04, 0x88, 0x04, 0x8f, 0x30, 0x0b, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x33, + 0x09, 0x04, 0x80, 0x88, 0x04, 0x80, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x2e, 0x0a, 0x30, 0x04, + 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x35, 0x0a, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, + 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, 0x33, 0x09, 0x30, 0x04, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x8f, 0x35, 0x0a, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x8b, 0x38, 0x0c, + 0x04, 0x83, 0x2e, 0x07, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x04, 0x8f, + 0x3a, 0x0b, 0x30, 0x04, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3d, 0x0c, 0x04, 0x80, 0x88, 0x04, 0x83, + 0x31, 0x05, 0x80, 0x80, 0x8c, 0x20, 0x04, 0x88, 0x06, 0x8f, 0x38, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, + 0x3d, 0x08, 0x8b, 0x3c, 0x0b, 0x04, 0x80, 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x04, 0x8f, 0x3d, 0x0c, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x8b, 0x3a, 0x0a, 0x04, 0x80, + 0x8c, 0x10, 0x04, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x3c, 0x0b, 0x30, 0x04, 0x80, + 0x82, 0x02, 0x83, 0x3d, 0x08, 0x9b, 0x3a, 0x09, 0x04, 0xa2, 0x83, 0x2e, 0x07, 0x88, 0x04, 0x83, 0x49, 0x04, 0x80, + 0x80, 0x88, 0x04, 0x88, 0x04, 0x8f, 0x3a, 0x0a, 0x30, 0x04, 0x83, 0x49, 0x04, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, + 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x8f, 0x38, 0x09, + 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x98, 0x06, 0x01, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, + 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x04, 0x8f, 0x3a, 0x09, 0x30, 0x04, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x98, 0x02, 0x08, 0x80, 0x88, 0x04, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x98, 0x01, 0x08, 0x88, 0x06, 0x88, + 0x04, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x0a, 0x03, 0x87, 0x3a, 0x02, 0x20, 0x95, 0x3a, 0x20, 0x37, + 0x22, 0x09, 0x50, 0x0f, 0x07, 0x9b, 0x3a, 0x07, 0x0f, 0xf0, 0x84, 0x61, 0x83, 0x25, 0x05, 0x80, 0x94, 0x81, 0x37, + 0x98, 0x04, 0xa1, 0x98, 0x04, 0xa2, 0x84, 0x61, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x0a, 0x04, 0x80, 0x84, + 0x61, 0x83, 0x30, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x98, 0x06, 0x01, 0x87, 0x22, 0x09, 0x30, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0b, 0x04, 0x80, 0x80, 0x83, 0x35, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, + 0x04, 0x81, 0x25, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8a, 0x0c, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0c, 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, + 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, + 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, + 0x37, 0x8b, 0x24, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, + 0x25, 0x87, 0x2c, 0x05, 0x30, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x20, 0x09, 0x04, 0x80, 0x80, 0x83, 0x2c, 0x05, 0x80, + 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x87, 0x2c, 0x05, 0x20, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x22, + 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8a, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x27, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, 0x05, 0x80, 0x94, 0x81, + 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x09, 0x04, 0x80, 0x80, 0x83, 0x36, + 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x27, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x24, 0x09, + 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x25, 0x80, + 0x80, 0x94, 0x91, 0x37, 0x8b, 0x20, 0x0a, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x06, + 0x81, 0x24, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x22, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8a, 0x0c, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x91, + 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x22, 0x80, 0x80, 0x95, 0x3a, 0x20, 0x37, 0x8a, 0x0c, 0x04, 0x83, 0x3a, 0x07, + 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8a, + 0x0b, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x80, 0x80, 0x80, 0x94, + 0x81, 0x37, 0x8b, 0x22, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, + 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x25, 0x09, 0x04, 0x80, 0x80, 0x83, 0x41, 0x05, 0x80, 0x94, 0x81, 0x37, + 0x88, 0x04, 0x88, 0x06, 0x81, 0x22, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0a, 0x04, 0x80, 0x80, 0x9b, 0x46, + 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x25, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x27, 0x0b, 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x29, 0x80, 0x80, + 0x94, 0x81, 0x37, 0x8b, 0x25, 0x0c, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, + 0x04, 0x81, 0x27, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x29, 0x0c, 0x04, 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, + 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x25, 0x88, 0x1b, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x24, 0x0b, + 0x04, 0x80, 0x80, 0x80, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x29, 0x80, 0x80, 0x94, 0x81, 0x37, + 0x8b, 0x25, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, + 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x24, 0x09, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, 0x80, 0x94, 0x81, 0x37, 0x88, + 0x04, 0x88, 0x04, 0x81, 0x25, 0x80, 0x80, 0x94, 0x81, 0x37, 0x8b, 0x20, 0x0a, 0x04, 0x80, 0x80, 0x83, 0x46, 0x05, + 0x80, 0x94, 0x81, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, 0x24, 0x80, 0x80, 0x94, 0x91, 0x37, 0x8b, 0x22, 0x09, 0x04, + 0x80, 0x80, 0x9b, 0x46, 0x04, 0x1b, 0xc1, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x04, 0x81, 0x20, 0x80, 0x80, + 0x94, 0x91, 0x37, 0x88, 0x04, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x91, 0x37, 0x88, 0x04, 0x88, 0x06, 0x81, + 0x22, 0x80, 0x80, 0x94, 0x91, 0x37, 0x98, 0x01, 0x08, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, 0x94, 0x91, 0x37, 0x98, + 0x02, 0x08, 0x88, 0x04, 0x80, 0x80, 0x80, 0x94, 0x91, 0x37, 0x98, 0x01, 0x08, 0x80, 0x80, 0x83, 0x3a, 0x05, 0x80, + 0x94, 0x91, 0x37, 0x98, 0x02, 0x08, 0x88, 0x06, 0x80, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x04, + 0x87, 0x3a, 0x02, 0x30, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x9b, 0x2e, 0x0b, 0x04, 0xa1, 0x83, 0x3a, 0x07, 0x80, 0x83, + 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x98, 0x04, 0xa2, 0x80, 0x80, 0x80, 0x94, 0x24, 0x37, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, + 0x01, 0x2e, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, + 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, + 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, + 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, + 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, + 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x3a, 0x0c, 0x30, 0x37, 0x98, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, + 0xa1, 0x80, 0x80, 0x94, 0x24, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, + 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0c, 0x30, 0x37, + 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, + 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x3a, 0x0b, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x98, 0x06, 0x10, 0x35, + 0x0c, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0b, 0x30, 0x37, 0x9b, 0x35, 0x0b, 0x04, 0xa1, 0x80, 0x98, + 0x06, 0x01, 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x9c, 0x20, 0x06, 0x01, 0x88, 0x04, 0x3a, 0x0b, + 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x30, 0x0b, 0x04, 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, + 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x35, 0x0a, 0x30, 0x04, + 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, 0x0a, 0x30, 0x37, 0x9b, 0x2c, 0x09, 0x04, 0xa1, 0x80, 0x9c, 0x14, 0x06, 0x01, + 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x37, 0x98, 0x06, 0x01, 0x88, 0x04, 0x30, 0x09, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x94, 0x24, 0x37, 0x9b, 0x2e, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x30, 0x84, + 0x81, 0x94, 0x22, 0x37, 0x98, 0x06, 0x01, 0x88, 0x06, 0x2c, 0x09, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x3a, + 0x09, 0x30, 0x37, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, 0x81, 0x94, 0x20, 0x37, + 0x98, 0x06, 0x01, 0x88, 0x04, 0x2e, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x37, 0x9b, 0x31, 0x0b, + 0x03, 0x11, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, 0x37, 0x98, 0x03, 0x21, 0x88, + 0x06, 0x98, 0x04, 0xa1, 0x80, 0x87, 0x38, 0x03, 0x30, 0x97, 0x38, 0x09, 0x30, 0x47, 0x9b, 0x2e, 0x0c, 0x04, 0xa1, + 0x83, 0x2c, 0x07, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x98, 0x04, + 0xa2, 0x31, 0x0b, 0x30, 0x03, 0x11, 0x80, 0x80, 0x94, 0x24, 0x47, 0x9b, 0x35, 0x0a, 0x04, 0xa1, 0x80, 0x98, 0x03, + 0x21, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x01, 0x2e, 0x0c, 0x30, + 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, + 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x35, 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x94, + 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, + 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x9b, 0x38, 0x0b, 0x04, 0xa1, + 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x12, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, + 0x04, 0xa1, 0x80, 0x80, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x80, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x38, 0x0b, 0x30, 0x04, 0xa1, 0x80, 0x80, 0x97, 0x38, 0x0c, 0x30, 0x47, 0x98, + 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, + 0x98, 0x04, 0xa1, 0x80, 0x80, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, + 0x84, 0x81, 0x94, 0x22, 0x47, 0x9a, 0x0a, 0x06, 0x01, 0x88, 0x06, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, + 0x0c, 0x30, 0x47, 0x9b, 0x31, 0x0a, 0x03, 0x08, 0x80, 0x98, 0x06, 0x01, 0x83, 0x3d, 0x05, 0x84, 0x81, 0x94, 0x28, + 0x47, 0x98, 0x03, 0x08, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x03, 0x08, 0x80, + 0x98, 0x06, 0x01, 0x87, 0x3d, 0x05, 0x20, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x03, 0x08, 0x98, 0x06, 0x10, 0x31, + 0x0a, 0x30, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0b, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, + 0x87, 0x3c, 0x05, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, + 0x81, 0x94, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x3c, 0x05, 0x14, 0x84, 0x81, 0x94, 0x20, + 0x47, 0x98, 0x06, 0x01, 0x98, 0x06, 0x20, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x97, 0x38, 0x0a, 0x30, 0x47, 0x9b, + 0x30, 0x0c, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x83, 0x49, 0x04, 0x84, 0x81, 0x94, 0x28, 0x47, 0x98, 0x06, 0x01, + 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x24, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, + 0x49, 0x04, 0x30, 0x84, 0x81, 0x94, 0x22, 0x47, 0x98, 0x06, 0x01, 0x88, 0x06, 0x30, 0x0c, 0x30, 0x04, 0xa1, 0x80, + 0x84, 0x81, 0x97, 0x38, 0x09, 0x30, 0x47, 0x98, 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x20, 0x84, + 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, 0x04, 0x98, 0x04, 0xa1, 0x80, 0x84, 0x81, 0x94, 0x30, 0x47, 0x98, + 0x04, 0xa1, 0x80, 0x98, 0x06, 0x01, 0x87, 0x49, 0x04, 0x18, 0x84, 0x81, 0x94, 0x20, 0x47, 0x98, 0x06, 0x01, 0x88, + 0x06, 0x98, 0x04, 0xa1, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x26, 0x03, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x9b, 0x2e, 0x0c, 0x06, 0x01, 0x83, 0x3a, 0x07, 0x97, 0x3a, 0x09, 0x30, 0x37, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x98, 0x04, 0xa3, 0x98, 0x04, 0xa2, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x98, 0x06, 0x01, + 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x87, 0x3d, + 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x82, + 0x37, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, + 0x04, 0x88, 0x04, 0x94, 0x82, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, + 0x37, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, + 0x37, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, + 0x08, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, + 0x37, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x37, 0x83, 0x31, 0x05, 0x80, 0x80, + 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, + 0x81, 0x37, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, 0x37, 0x80, 0x8a, 0x02, 0x0a, + 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, + 0x06, 0x94, 0x81, 0x30, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x83, 0x3a, 0x07, 0x94, 0x81, 0x30, 0x83, + 0x49, 0x04, 0x80, 0x80, 0x88, 0x04, 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x88, + 0x06, 0x80, 0x94, 0x81, 0x30, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x04, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x06, + 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, + 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, 0x9b, 0x3a, 0x02, 0x0a, 0x0a, + 0x83, 0x3d, 0x08, 0x88, 0x06, 0x83, 0x3a, 0x07, 0x94, 0x81, 0x30, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, + 0x88, 0x04, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, + 0x87, 0x3d, 0x05, 0x18, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x94, 0x81, 0x30, 0x80, 0x8a, 0x02, 0x0a, 0x87, + 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x94, 0x81, 0x30, 0x87, 0x3d, 0x05, 0x1c, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, + 0x04, 0x84, 0x81, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x88, 0x06, 0x80, 0x84, 0x81, 0x83, 0x3d, 0x05, + 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x84, 0x81, 0x80, 0x82, 0x02, 0x83, 0x3d, 0x08, 0x88, 0x06, 0x80, 0x84, + 0x81, 0x83, 0x49, 0x04, 0x80, 0x80, 0x88, 0x06, 0x88, 0x04, 0x84, 0x81, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x88, 0x06, 0x80, 0x84, 0x81, 0x80, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, 0x06, 0x84, 0x81, 0x80, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x88, 0x06, 0x80, 0x84, 0x81, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x88, 0x06, 0x88, + 0x04, 0x84, 0x81, 0x3d, 0x05, 0x24, 0x02, 0x10, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, + 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x83, 0x3d, 0x08, 0x80, 0x80, 0x80, + 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x82, 0x02, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, + 0x80, 0x83, 0x31, 0x05, 0x80, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x80, + 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, + 0x18, 0x80, 0x80, 0x80, 0x83, 0x3d, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x82, 0x02, 0x83, 0x3d, + 0x08, 0x80, 0x83, 0x3a, 0x07, 0x80, 0x83, 0x49, 0x04, 0x80, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, 0x82, 0x02, 0x87, + 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, 0x31, 0x05, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x06, 0x80, 0x80, 0x8a, 0x02, + 0x0a, 0x87, 0x3d, 0x08, 0x14, 0x80, 0x80, 0x80, 0x83, 0x49, 0x04, 0x88, 0x0a, 0x80, 0x80, 0x88, 0x04, 0x80, 0x80, + 0x8a, 0x02, 0x0a, 0x87, 0x3d, 0x08, 0x18, 0x80, 0x80, 0x80, 0x83, 0x4b, 0x04, 0x88, 0x0a, 0x82, 0x0c, 0x80, 0x88, + 0x06, 0x80, 0x80, 0x07, 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x3a, 0x3a, 0x7e, 0x7e, 0x44, 0x72, 0x30, + 0x5a, 0x45, 0x52, 0x69, 0x58, 0x7e, 0x7e, 0x3a, 0x3a, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x09, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x0f, 0xf3, 0x28, 0xb8, 0x40, 0xa1, 0x77, 0xb1, 0xe5, 0x7b, 0x7f, 0x61, 0xe7, + 0xd1, 0x14, 0x37, 0xb5, 0x3f, 0xea, 0xf6, 0xc6, 0x77, 0x9b, 0x39, 0xb9, 0x76, 0xb1, 0xe8, 0x67, 0xb8, 0xed, 0x1b, + 0xf1, 0x26, 0x19, 0x8b, 0x45, 0x09, 0x1f, 0xb8, 0x39, 0xe1, 0x1e, 0x00, 0xa1, 0x95, 0x62, 0x8f, 0xa3, 0x0f, 0x30, + 0xcf, 0x25, 0xd0, 0x2c, 0xd7, 0x34, 0xcc, 0x19, 0xf4, 0x4a, 0x8f, 0x5d, 0xe5, 0xc7, 0x5a, 0xca, 0xe5, 0x21, 0x04, + 0x1b, 0xc5, 0x0c, 0x4f, 0x9c, 0x1d, 0x37, 0x99, 0x53, 0xe5, 0xef, 0x3e, 0xa3, 0x57, 0xde, 0xd6, 0x34, 0xf1, 0xf7, + 0xf9, 0x38, 0x9f, 0x59, 0xdf, 0x21, 0xc7, 0x21, 0xef, 0x08, 0x01, 0x00, 0x1b, 0xe4, 0xe1, 0x4b, 0xe9, 0xb7, 0x55, + 0xde, 0xf1, 0x19, 0xe8, 0x0f, 0x11, 0xcf, 0x7b, 0x5d, 0x4d, 0x27, 0xdd, 0xcc, 0x4c, 0xb7, 0x68, 0x91, 0x27, 0x4a, + 0x87, 0x37, 0x0c, 0xda, 0xfb, 0x56, 0xc9, 0xd9, 0x48, 0xc7, 0x59, 0x6b, 0x97, 0x93, 0x3b, 0x0f, 0xb4, 0x41, 0xd4, + 0x1c, 0x27, 0xa7, 0x43, 0x03, 0xb1, 0x77, 0xa0, 0xff, 0x61, 0x77, 0x79, 0xff, 0x80, 0x80, 0xbc, 0x35, 0xc7, 0x18, + 0xff, 0x12, 0xdf, 0x49, 0x6f, 0xa3, 0xa8, 0xf5, 0x39, 0xcf, 0xf7, 0x2a, 0x1c, 0xa3, 0x1b, 0x3a, 0xe7, 0x02, 0xc2, + 0x51, 0xbf, 0x29, 0x04, 0xe3, 0x43, 0x9b, 0x73, 0x79, 0x38, 0x4c, 0xab, 0xf7, 0x39, 0xf7, 0xd8, 0x34, 0xcd, 0x3a, + 0x91, 0x8f, 0xbd, 0xc8, 0x7b, 0xae, 0x09, 0xfe, 0x29, 0xdf, 0x08, 0xe8, 0x34, 0xc1, 0x21, 0x0b, 0xef, 0xf2, 0x0f, + 0x0a, 0xf5, 0xf5, 0x24, 0xb1, 0x7d, 0x91, 0x49, 0xbf, 0x53, 0x85, 0x79, 0xcb, 0xd6, 0x6f, 0xaf, 0xf3, 0x3d, 0xe5, + 0xdb, 0x21, 0x20, 0xdf, 0x01, 0xef, 0x3e, 0xa7, 0x4a, 0xe1, 0xd1, 0x5a, 0xc3, 0x12, 0xfc, 0x05, 0x13, 0xe4, 0x08, + 0x01, 0xf7, 0x32, 0xca, 0xe4, 0x3f, 0xea, 0x13, 0xd4, 0x2c, 0xfd, 0xb7, 0x64, 0xbc, 0x2d, 0xd4, 0x54, 0x83, 0x65, + 0xc7, 0x45, 0xaa, 0x25, 0x41, 0x76, 0x29, 0x53, 0xce, 0xff, 0x2d, 0xa8, 0x2b, 0x31, 0x9f, 0x51, 0x9f, 0x89, 0x98, + 0x1f, 0x20, 0xac, 0x40, 0x01, 0xe4, 0xff, 0x11, 0x2f, 0xc1, 0xeb, 0x5d, 0x9b, 0x22, 0x3f, 0x94, 0x5a, 0xf1, 0xfd, + 0xcf, 0x09, 0x1f, 0x05, 0x0c, 0xe7, 0xd1, 0x2f, 0x15, 0xf3, 0xe1, 0x27, 0xf1, 0x20, 0xcf, 0xed, 0x33, 0xf9, 0x0b, + 0x08, 0xb5, 0x2f, 0x0b, 0xe7, 0x2f, 0xb7, 0x45, 0xe3, 0x01, 0xfb, 0x10, 0xff, 0xdd, 0x29, 0xf0, 0xef, 0x11, 0x3f, + 0xa1, 0x07, 0x3c, 0xb1, 0x3c, 0xef, 0x21, 0xdf, 0xe1, 0x4f, 0xa5, 0x1b, 0x4e, 0xa7, 0x24, 0x10, 0xb3, 0x45, 0xef, + 0xff, 0x12, 0xc0, 0x4f, 0xf9, 0xc3, 0x37, 0xee, 0xdb, 0x65, 0xa4, 0xff, 0x15, 0x47, 0xc1, 0xff, 0xfc, 0xe5, 0x2a, + 0x10, 0xf5, 0xbd, 0x49, 0x2b, 0x83, 0x3d, 0xf7, 0x3a, 0xd2, 0xdb, 0x2a, 0xdf, 0x27, 0x12, 0xe8, 0xe7, 0x05, 0x23, + 0xdc, 0xf1, 0x22, 0x0e, 0x0b, 0xc6, 0xfb, 0x3f, 0xe3, 0xfd, 0x01, 0xfd, 0x17, 0xc1, 0x2b, 0x2f, 0x97, 0x89, 0x71, + 0x6a, 0xb5, 0x21, 0x1f, 0xc1, 0x3f, 0xe9, 0xe7, 0xf9, 0x37, 0xbe, 0x57, 0xb3, 0x29, 0xc1, 0x3f, 0x1b, 0xbd, 0x0a, + 0x3c, 0xcd, 0xe4, 0x31, 0xef, 0x0a, 0x02, 0xe0, 0x1d, 0xdf, 0x21, 0x27, 0xa5, 0x2f, 0x0d, 0xef, 0x0c, 0xbd, 0x42, + 0x46, 0x75, 0x4a, 0x00, 0xd9, 0x17, 0x11, 0xe0, 0x02, 0x55, 0x81, 0x3c, 0x13, 0xd1, 0x28, 0xe2, 0x12, 0x1b, 0xb1, + 0x2b, 0x4b, 0x7a, 0x5b, 0x05, 0xa3, 0x4c, 0x09, 0xd0, 0x37, 0xe1, 0xc7, 0x61, 0xb3, 0x42, 0xf1, 0xed, 0x0b, 0xe2, + 0xfc, 0x3b, 0xf9, 0xb4, 0x71, 0xc3, 0xef, 0xfb, 0x35, 0xe1, 0xf7, 0xfd, 0x37, 0x9d, 0x37, 0x11, 0x24, 0x77, 0x99, + 0xa7, 0xed, 0x3f, 0xf9, 0xdb, 0x24, 0x05, 0x9f, 0x93, 0x8e, 0x2b, 0x41, 0x80, 0x5f, 0xf9, 0xb7, 0x34, 0x2d, 0xc7, + 0x09, 0xee, 0x11, 0x23, 0xa1, 0x5d, 0x0f, 0x91, 0x77, 0x99, 0x2f, 0x26, 0xef, 0xd3, 0x2c, 0xc0, 0x2d, 0x3f, 0x95, + 0x23, 0x39, 0xbf, 0x11, 0xdb, 0x15, 0x5f, 0x89, 0x2c, 0xfb, 0x01, 0xbf, 0xa6, 0x9b, 0xbf, 0x81, 0x80, 0x5f, 0xcf, + 0x01, 0x31, 0xf4, 0xd3, 0x0f, 0xf2, 0x17, 0x29, 0xd8, 0xdb, 0x4f, 0xae, 0x1d, 0x3a, 0xb9, 0x27, 0xe1, 0x1f, 0xd1, + 0x38, 0xc2, 0x65, 0xa1, 0x0f, 0x35, 0xa7, 0x44, 0x15, 0xdb, 0xf9, 0x07, 0xcd, 0x5b, 0xf9, 0x9f, 0x70, 0xd1, 0xef, + 0x2b, 0x9a, 0x8b, 0xf1, 0x9b, 0x1d, 0x37, 0xbc, 0x58, 0xad, 0x1f, 0x26, 0xbb, 0x1f, 0x09, 0xbf, 0x78, 0xd9, 0xcb, + 0x04, 0x2a, 0xcf, 0x57, 0xad, 0x1a, 0x19, 0xd1, 0x27, 0xc9, 0x27, 0x29, 0xd2, 0xdb, 0x43, 0xde, 0xee, 0x43, 0x0d, + 0x87, 0x3c, 0x29, 0xd3, 0x0c, 0x01, 0x15, 0xfb, 0xaf, 0x65, 0xc4, 0x17, 0x1e, 0xf3, 0xbf, 0x4e, 0xc3, 0x37, 0x0a, + 0xde, 0xed, 0x18, 0xfc, 0xe1, 0x4e, 0xa9, 0x47, 0xe3, 0xd6, 0x4f, 0x99, 0x6b, 0x05, 0xbc, 0xeb, 0x5b, 0x9a, 0x4b, + 0x0c, 0xb2, 0x2b, 0x29, 0xce, 0x09, 0xc6, 0x79, 0xef, 0x82, 0x76, 0xf0, 0xb9, 0x42, 0x07, 0xe7, 0x14, 0xbc, 0x60, + 0xb1, 0x10, 0x27, 0x09, 0xcf, 0xf1, 0x27, 0x1b, 0xbf, 0x2b, 0xf7, 0xed, 0x1f, 0xf3, 0xf1, 0x11, 0xfb, 0x23, 0xa6, + 0x4b, 0xfc, 0xf9, 0xcf, 0x6d, 0x86, 0x2d, 0x49, 0x8f, 0x31, 0x1c, 0xc9, 0x4a, 0x99, 0x4e, 0xf1, 0xf1, 0x03, 0x39, + 0x8c, 0x5f, 0xe1, 0xf7, 0x0d, 0x20, 0xc5, 0x06, 0x1e, 0xf2, 0xec, 0x0c, 0x49, 0xb2, 0xe9, 0x2d, 0x12, 0xb6, 0x4f, + 0xe9, 0xed, 0xf6, 0x49, 0x85, 0x76, 0xe1, 0xda, 0x25, 0xcc, 0x3c, 0xf1, 0xe7, 0x39, 0xd0, 0x05, 0xfb, 0x0b, 0xe9, + 0x43, 0xc9, 0x11, 0xd6, 0x33, 0xdc, 0x26, 0xea, 0xfe, 0x19, 0xe1, 0xe2, 0x27, 0x31, 0x97, 0x59, 0xd7, 0x19, 0xdb, + 0x15, 0x17, 0xe6, 0xed, 0x36, 0xe0, 0xbf, 0x75, 0xc8, 0x1f, 0xd5, 0xd5, 0x7b, 0xa9, 0x12, 0x21, 0xc8, 0x2b, 0x11, + 0xb4, 0x23, 0x25, 0xec, 0xd7, 0x49, 0xa4, 0x53, 0xf1, 0xcf, 0x20, 0x21, 0xbb, 0x45, 0xc5, 0x1b, 0xff, 0x38, 0xa1, + 0x1b, 0x13, 0x21, 0xad, 0x46, 0xdc, 0x27, 0xcb, 0x27, 0xe3, 0xe2, 0x63, 0xf9, 0x7f, 0x71, 0xdb, 0x0d, 0x02, 0xfc, + 0xf4, 0xf3, 0x31, 0xd9, 0xe9, 0x2f, 0x15, 0xdb, 0xcb, 0x7a, 0x64, 0x87, 0x01, 0xc0, 0xcf, 0x81, 0xb0, 0x0b, 0x22, + 0xcb, 0x32, 0xb8, 0x4e, 0xd0, 0x06, 0x19, 0x06, 0xeb, 0xef, 0x11, 0xf1, 0x1d, 0x11, 0xd1, 0xff, 0x01, 0x2f, 0xe9, + 0xcf, 0x50, 0xd9, 0xef, 0x31, 0xb7, 0x19, 0x4f, 0xb1, 0x0c, 0xfb, 0x09, 0x07, 0x19, 0xdf, 0xe2, 0x4f, 0xa7, 0x29, + 0xf1, 0x25, 0xf6, 0xfd, 0xcf, 0x4f, 0xdb, 0xbd, 0x87, 0xb1, 0xe9, 0x3d, 0xe3, 0xf7, 0x19, 0xde, 0x11, 0x2b, 0x9e, + 0x39, 0x12, 0xf1, 0xfb, 0x02, 0x0b, 0xdb, 0x28, 0xf5, 0xe0, 0x29, 0x19, 0xb5, 0x11, 0x43, 0xb1, 0x0f, 0x51, 0xa0, + 0x1f, 0xf9, 0x07, 0x15, 0xd0, 0x37, 0xdb, 0xf5, 0x25, 0xfb, 0xf5, 0xbf, 0xa1, 0x70, 0x0e, 0x39, 0x02, 0xc1, 0x36, + 0xfe, 0xe1, 0x1d, 0xfe, 0xfe, 0xd7, 0x16, 0x4b, 0x8b, 0x50, 0xc5, 0x4f, 0xbb, 0x25, 0xd9, 0x27, 0xf1, 0xec, 0x33, + 0xc4, 0x3b, 0xe2, 0xd7, 0x58, 0x95, 0x4b, 0x11, 0xcd, 0x17, 0x07, 0xee, 0xef, 0x27, 0xf9, 0xf8, 0x0a, 0xeb, 0xf2, + 0x3b, 0xc5, 0x21, 0xf7, 0x11, 0xbf, 0x45, 0xf0, 0xfb, 0x0c, 0xf9, 0xea, 0x05, 0x08, 0x25, 0xdf, 0xe9, 0x35, 0xe7, + 0xbf, 0x7d, 0x8f, 0x63, 0xb8, 0x19, 0xea, 0x12, 0x29, 0x9f, 0x68, 0xc7, 0xff, 0x04, 0xf7, 0x42, 0xa1, 0x55, 0xac, + 0x37, 0x04, 0xe9, 0x00, 0x12, 0xf5, 0x01, 0xfc, 0x08, 0xfb, 0x06, 0xfb, 0x0f, 0xcb, 0x35, 0x11, 0xd0, 0xf0, 0x3c, + 0xe3, 0xe9, 0x2d, 0xe3, 0xff, 0x09, 0x30, 0x9b, 0x23, 0x47, 0xcb, 0xdf, 0x4d, 0xb1, 0x27, 0x0b, 0x03, 0xe1, 0xcc, + 0x9f, 0x8a, 0xf7, 0x3a, 0xee, 0xf1, 0xef, 0x4d, 0xa3, 0x3f, 0xd2, 0x2a, 0xe5, 0x09, 0x1d, 0xd1, 0x0b, 0x07, 0x00, + 0xff, 0x21, 0xad, 0x63, 0xca, 0xcf, 0x6e, 0xcb, 0xfe, 0xdf, 0x51, 0xbb, 0x15, 0x12, 0xd7, 0x3c, 0xcf, 0x04, 0x07, + 0xe9, 0x47, 0xd1, 0xe3, 0x25, 0xf6, 0x01, 0x21, 0xbf, 0x30, 0xec, 0x15, 0xe7, 0xde, 0x5f, 0xaf, 0x39, 0xc8, 0x38, + 0xbf, 0x3f, 0x0a, 0x97, 0x44, 0x21, 0xf0, 0xbf, 0x5d, 0xcc, 0xef, 0x28, 0x15, 0x99, 0x52, 0x15, 0xcc, 0xea, 0x4d, + 0xd9, 0xfd, 0xf0, 0x57, 0x6c, 0x5f, 0x19, 0xc8, 0xef, 0x41, 0xd3, 0x01, 0x2b, 0xcb, 0x16, 0xff, 0x0d, 0xee, 0xee, + 0x2d, 0xd6, 0x43, 0xc1, 0x11, 0xcf, 0x91, 0x79, 0x13, 0x10, 0x21, 0xd7, 0x0b, 0x01, 0xf7, 0x19, 0xf7, 0x09, 0xcb, + 0x25, 0x32, 0xab, 0x2e, 0xdd, 0x30, 0xe7, 0x01, 0xff, 0xf4, 0x1c, 0xe1, 0x21, 0xe2, 0x11, 0xf3, 0x29, 0xdd, 0xe3, + 0x3f, 0xe1, 0x0f, 0xd1, 0x3f, 0xc5, 0x21, 0x02, 0x09, 0xd9, 0x0e, 0x3c, 0xb1, 0xff, 0x38, 0xed, 0xd3, 0x50, 0xd5, + 0xdc, 0x20, 0x2f, 0xd5, 0xdb, 0x41, 0xd9, 0x13, 0xfd, 0xf5, 0xf5, 0x19, 0x2f, 0x99, 0x2b, 0x01, 0x2e, 0xc5, 0x19, + 0xe0, 0x17, 0x28, 0xc9, 0x05, 0xfe, 0x44, 0xb1, 0x07, 0x1e, 0xd7, 0x3f, 0xdd, 0x0c, 0xb7, 0x68, 0xed, 0xc8, 0x17, + 0x29, 0xdd, 0xf2, 0x13, 0xf9, 0x17, 0xdd, 0x19, 0xf6, 0xf8, 0x19, 0xf1, 0x00, 0xef, 0x21, 0xfb, 0xe5, 0x10, 0x07, + 0x01, 0xe5, 0x2b, 0xda, 0x11, 0xff, 0x06, 0xeb, 0x13, 0xeb, 0x21, 0x02, 0xb3, 0x6b, 0xce, 0xf9, 0xec, 0x5a, 0x95, + 0x15, 0x55, 0x8b, 0x56, 0xd9, 0x09, 0xf8, 0x07, 0x13, 0xe4, 0xf9, 0x0f, 0x29, 0xb9, 0x17, 0x1d, 0xd8, 0x36, 0xbd, + 0x27, 0xf8, 0x21, 0xb8, 0x1f, 0x34, 0xc9, 0xeb, 0x3c, 0xfd, 0xa1, 0x82, 0xcd, 0xc8, 0x2b, 0x4d, 0x8b, 0x24, 0x21, + 0xe8, 0xe9, 0x2a, 0xf3, 0xea, 0x1f, 0xe0, 0x2b, 0xc6, 0x1f, 0x31, 0xb4, 0x1b, 0xf4, 0x2f, 0xad, 0x67, 0xa2, 0x37, + 0xf7, 0xf5, 0xfb, 0x10, 0x01, 0x00, 0xf9, 0x0e, 0xcf, 0x3e, 0xe5, 0x0f, 0xd1, 0x3f, 0xd3, 0x0b, 0x0b, 0xf0, 0x0f, + 0xfb, 0xfb, 0x03, 0xfb, 0xfe, 0x1f, 0xe9, 0xef, 0x23, 0xdd, 0x0b, 0x1b, 0xe7, 0xed, 0x23, 0xf3, 0xf3, 0x1d, 0xdf, + 0x21, 0xfa, 0xe6, 0xf7, 0x43, 0xbc, 0x2f, 0xea, 0xf9, 0xf3, 0x36, 0xe9, 0xda, 0x17, 0x2a, 0xcf, 0xed, 0x2a, 0x1c, + 0xa5, 0x57, 0xd8, 0x0c, 0xd9, 0x3b, 0xf7, 0xde, 0xef, 0x50, 0xd1, 0xdb, 0x4b, 0xe9, 0xc5, 0x49, 0xe3, 0x07, 0xed, + 0x1b, 0xe5, 0x17, 0xf5, 0xff, 0x09, 0xea, 0x05, 0x39, 0xb0, 0x0f, 0x34, 0xd5, 0x08, 0xf3, 0x0d, 0x17, 0xf1, 0xcf, + 0x3a, 0x07, 0xbd, 0x4e, 0xdf, 0xd5, 0x4f, 0xd9, 0x01, 0xd7, 0x40, 0x09, 0xd8, 0xdb, 0x50, 0xdd, 0x08, 0xe7, 0x19, + 0xf7, 0x01, 0xff, 0x01, 0xdf, 0x4a, 0xd2, 0x09, 0xd1, 0x46, 0xfd, 0xdc, 0x03, 0xf6, 0x42, 0xb3, 0x23, 0xff, 0xfb, + 0xe9, 0x37, 0xe1, 0xed, 0x08, 0x33, 0xda, 0xd8, 0x3d, 0xd2, 0x45, 0xa8, 0x46, 0xd0, 0x23, 0xde, 0x38, 0xbe, 0x1d, + 0xff, 0x11, 0xe4, 0xf7, 0x36, 0xdf, 0xdf, 0x41, 0xea, 0xd5, 0x23, 0x1e, 0xd8, 0xe3, 0x58, 0xa5, 0x4f, 0xb9, 0x3f, + 0xc1, 0x33, 0x03, 0xdf, 0xf2, 0x25, 0x03, 0xdd, 0x23, 0xe1, 0x0f, 0x11, 0xdc, 0x09, 0x1e, 0xf2, 0xf3, 0x13, 0xf5, + 0xe4, 0x3b, 0xd1, 0x1a, 0xf1, 0x0f, 0xee, 0x05, 0x00, 0x08, 0x08, 0xe5, 0x0d, 0x0d, 0xec, 0xfb, 0x26, 0xdb, 0x0b, + 0xfb, 0x10, 0xee, 0x05, 0x11, 0xee, 0x01, 0x03, 0xff, 0x01, 0xff, 0x08, 0xf3, 0x0c, 0xf2, 0x16, 0xe6, 0x0b, 0x01, + 0x09, 0xfe, 0xe4, 0x21, 0xf8, 0xf0, 0x11, 0x0a, 0xe9, 0xfb, 0x20, 0xed, 0xf7, 0x0c, 0x03, 0xfe, 0xf6, 0x0c, 0xe9, + 0x20, 0xfc, 0xf5, 0xf0, 0x0b, 0x14, 0xf9, 0xe6, 0x1d, 0xf4, 0x09, 0xf8, 0xe6, 0x29, 0x07, 0xdc, 0x05, 0x0b, 0xed, + 0x2c, 0xe8, 0xfd, 0xed, 0x1d, 0x0b, 0xdb, 0xff, 0x31, 0xea, 0xea, 0xef, 0x3c, 0xd1, 0x1b, 0xfe, 0xfb, 0xd5, 0x3a, + 0x07, 0xb9, 0x4c, 0xe9, 0xed, 0x05, 0xef, 0x43, 0xbe, 0x28, 0xe2, 0x0b, 0xf3, 0x27, 0xd7, 0x1b, 0xfd, 0xf3, 0xf2, + 0x2f, 0xcb, 0x2b, 0xfb, 0xe7, 0xfb, 0x1b, 0x0e, 0xc7, 0x28, 0x05, 0xf8, 0xe7, 0x26, 0xdf, 0x1b, 0xf9, 0x04, 0xd7, + 0x38, 0xf5, 0xf4, 0xe2, 0x1d, 0x21, 0xe4, 0xf1, 0xf5, 0x2f, 0xd9, 0x29, 0xd5, 0x0f, 0x09, 0xf8, 0xfb, 0xfb, 0x09, + 0x0b, 0x11, 0xc5, 0x13, 0x31, 0xc2, 0x32, 0xe7, 0x01, 0xed, 0x28, 0xfa, 0xd9, 0x1c, 0x02, 0x16, 0xb6, 0x35, 0xfd, + 0x09, 0xec, 0x13, 0xec, 0xfa, 0x11, 0x11, 0xe5, 0x03, 0x03, 0x05, 0xf7, 0x05, 0x03, 0x00, 0xf6, 0x17, 0xdb, 0x1f, + 0xf5, 0xfa, 0x26, 0xd1, 0xf3, 0x24, 0x21, 0xae, 0x41, 0xe4, 0x02, 0xfc, 0x1e, 0xd6, 0xfe, 0x42, 0xd3, 0xeb, 0x05, + 0x27, 0xf9, 0xda, 0x19, 0xfa, 0x1b, 0xc7, 0x3c, 0xd9, 0xf1, 0x4f, 0xba, 0x0a, 0xf7, 0x3a, 0xaf, 0x4a, 0xcc, 0x15, + 0x06, 0xf7, 0xee, 0x29, 0xe6, 0x03, 0xff, 0x01, 0xf7, 0x0f, 0x01, 0x01, 0xec, 0x17, 0xea, 0x17, 0xd7, 0x3f, 0xe0, + 0xf3, 0x06, 0x0e, 0xfb, 0xdb, 0x55, 0xae, 0x23, 0x02, 0x01, 0xdb, 0x30, 0xfd, 0xd9, 0x2a, 0xdd, 0x1f, 0xf1, 0x03, + 0xdd, 0x4f, 0xc9, 0xe7, 0x32, 0xff, 0xdb, 0x32, 0xce, 0x19, 0xeb, 0x3d, 0xb4, 0x1d, 0x0d, 0x06, 0xef, 0xe6, 0x2a, + 0xf3, 0x13, 0xc5, 0x45, 0xd9, 0x07, 0xf9, 0x17, 0xd2, 0x3f, 0xeb, 0xd1, 0x35, 0xeb, 0x09, 0xff, 0xff, 0xe5, 0x37, + 0xe1, 0xef, 0x20, 0xf7, 0xec, 0x21, 0xdd, 0x0f, 0xfe, 0x19, 0xde, 0x10, 0xe9, 0x26, 0xed, 0xeb, 0x24, 0xfb, 0xf7, + 0xdf, 0x47, 0xb9, 0x3b, 0xe9, 0xf8, 0xf4, 0x1f, 0xf3, 0xf1, 0x16, 0xf9, 0xf9, 0x12, 0xe4, 0x04, 0x1e, 0xf9, 0xe1, + 0x20, 0xe8, 0x0a, 0x12, 0xdd, 0x17, 0x0f, 0xe5, 0xe7, 0x3d, 0xdb, 0x0d, 0xf7, 0x08, 0x03, 0xe9, 0x1d, 0xe6, 0x1d, + 0xf8, 0xee, 0x04, 0x05, 0x0a, 0xf9, 0xf3, 0x06, 0x19, 0xdb, 0x1d, 0xe7, 0x0c, 0x09, 0x08, 0xe4, 0xf9, 0x2c, 0xda, + 0x21, 0xd9, 0x15, 0xfd, 0x0e, 0xf3, 0xd7, 0x50, 0xd9, 0x02, 0xfb, 0xf3, 0x0f, 0x1b, 0xce, 0x17, 0x11, 0xd7, 0x39, + 0xc4, 0x1b, 0x03, 0x0d, 0xe3, 0x0d, 0x05, 0xff, 0xef, 0x1d, 0xf5, 0xef, 0x19, 0xe5, 0x0a, 0x1d, 0xdd, 0xfb, 0x23, + 0xf7, 0xe1, 0x0d, 0x15, 0xfe, 0xf1, 0x06, 0xe8, 0x11, 0x25, 0xe8, 0xe9, 0x02, 0x29, 0xd6, 0x08, 0x0d, 0xf7, 0x0d, + 0x06, 0xdb, 0xeb, 0x58, 0xd1, 0xf7, 0x11, 0xef, 0x04, 0x0c, 0x0d, 0xc1, 0x40, 0x03, 0xc7, 0x31, 0xdf, 0x2a, 0xd6, + 0x39, 0xb3, 0x23, 0xf9, 0x25, 0xe4, 0xed, 0x26, 0xed, 0xff, 0x07, 0xe7, 0x1e, 0x0e, 0xcf, 0x27, 0xdd, 0x1b, 0x03, + 0xfc, 0xe9, 0x25, 0xe3, 0xff, 0x21, 0xe9, 0xe7, 0x3d, 0xda, 0x01, 0xf4, 0x19, 0xeb, 0x08, 0x23, 0xbe, 0x0f, 0x2b, + 0xf2, 0xcb, 0x4f, 0xc2, 0x27, 0xf7, 0xf1, 0xf6, 0x1d, 0x18, 0xca, 0x0b, 0x21, 0xcc, 0x31, 0xf6, 0xd9, 0x33, 0xe9, + 0x00, 0xf3, 0x0c, 0x15, 0xf5, 0xe6, 0x25, 0xc9, 0x2c, 0x00, 0x07, 0xd9, 0x16, 0x07, 0xf7, 0x13, 0xdd, 0x12, 0x13, + 0xd9, 0x13, 0xf9, 0x21, 0xdb, 0x15, 0xf7, 0x01, 0xf6, 0x19, 0xe9, 0x17, 0xe2, 0x14, 0xf0, 0x0a, 0x29, 0xb2, 0x49, + 0xbf, 0x33, 0xf1, 0xce, 0x4b, 0xf1, 0xe7, 0xf3, 0x32, 0xcc, 0x23, 0x0f, 0xca, 0x19, 0x11, 0xfc, 0xc5, 0x5c, 0xdd, + 0xe3, 0x28, 0xd7, 0x1d, 0xff, 0x05, 0xd7, 0x2d, 0xf1, 0xff, 0xfa, 0x09, 0x08, 0xe5, 0x24, 0xed, 0xf7, 0x04, 0x1b, + 0xe2, 0xf5, 0x25, 0xee, 0xf6, 0xff, 0x31, 0xba, 0x1f, 0x11, 0xe7, 0xff, 0x12, 0xfa, 0xfd, 0x01, 0xf3, 0x1f, 0xd4, + 0x37, 0xdb, 0x01, 0x15, 0xe0, 0x22, 0xd7, 0x3d, 0xd7, 0xeb, 0x30, 0xea, 0x04, 0xf3, 0x11, 0xef, 0x19, 0xe4, 0x0e, + 0xfb, 0x19, 0xd2, 0x23, 0x05, 0xc7, 0x40, 0x01, 0xd5, 0x07, 0x1b, 0xf1, 0xef, 0x31, 0xc0, 0x1f, 0x19, 0xdb, 0xfd, + 0x0b, 0x1e, 0xe2, 0x05, 0x05, 0xe4, 0x34, 0xd3, 0x1b, 0xf5, 0x01, 0xf4, 0x1b, 0xdb, 0x26, 0xe3, 0x26, 0xe8, 0xe1, + 0x20, 0x14, 0xdd, 0xfb, 0x2d, 0xdd, 0xfc, 0x13, 0x03, 0xd9, 0x2b, 0xf9, 0xf3, 0xf9, 0x05, 0x20, 0xcf, 0x27, 0xf2, + 0xfe, 0x01, 0xf7, 0x1d, 0xde, 0x05, 0x35, 0xac, 0x23, 0x18, 0xe5, 0x13, 0xef, 0x1d, 0xd1, 0x0b, 0x1a, 0xfd, 0xf5, + 0x01, 0xfb, 0x07, 0x01, 0xed, 0x23, 0xe6, 0x0e, 0xfd, 0xf0, 0x11, 0xef, 0x1f, 0xfd, 0xdb, 0x04, 0x25, 0xfb, 0xd9, + 0x27, 0xea, 0x14, 0xed, 0x00, 0x06, 0xf3, 0x22, 0x0b, 0xbb, 0x25, 0xff, 0x11, 0xef, 0xfc, 0x01, 0x0c, 0x02, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x06, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0xd3, 0x06, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, + 0x16, 0x09, 0x12, 0x21, 0xfb, 0xa9, 0x0c, 0x0d, 0xd4, 0x00, 0x0f, 0x0e, 0x0e, 0xcb, 0x1b, 0x13, 0xb8, 0x10, 0xcb, + 0x00, 0x11, 0x14, 0xe5, 0xf9, 0x16, 0xf5, 0xe6, 0x11, 0x2b, 0x17, 0xfa, 0x0a, 0x0c, 0x08, 0x05, 0xc0, 0x03, 0x29, + 0x11, 0x05, 0x18, 0x0f, 0xe0, 0xba, 0x18, 0x0f, 0x0a, 0x0e, 0x0f, 0x1c, 0x05, 0xc1, 0x0f, 0x14, 0x29, 0x0a, 0x0b, + 0x0a, 0x07, 0x00, 0x0a, 0x03, 0xef, 0x11, 0x0a, 0x05, 0xe2, 0xe6, 0x0e, 0x0e, 0xf9, 0xcb, 0xa9, 0x0b, 0x19, 0x11, + 0x16, 0x04, 0xf2, 0xd9, 0x16, 0x1f, 0x1e, 0xf9, 0xbc, 0x04, 0x08, 0x09, 0x0a, 0xba, 0xcf, 0x14, 0x10, 0x03, 0x1f, + 0x0c, 0xb8, 0x04, 0x0b, 0xcd, 0x00, 0x07, 0x13, 0x19, 0x06, 0x27, 0xde, 0x0d, 0x15, 0x16, 0xfc, 0x13, 0x18, 0x0e, + 0x0b, 0xf1, 0xf4, 0x0a, 0xbb, 0xeb, 0xdd, 0x1c, 0x06, 0x0a, 0x0f, 0x07, 0x07, 0x08, 0x07, 0x2b, 0x16, 0x0c, 0x0a, + 0x05, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x16, 0x08, 0xc2, 0x11, 0x11, 0x08, 0x07, 0x0d, 0xe4, 0xba, 0xa2, + 0xc7, 0x14, 0x16, 0x13, 0x16, 0xeb, 0xbc, 0x00, 0x09, 0x16, 0x1f, 0x22, 0x01, 0x00, 0x09, 0x0a, 0x0c, 0xd0, 0x02, + 0x0e, 0xfe, 0xd7, 0x2b, 0x0f, 0x05, 0x0c, 0x0c, 0x08, 0xc7, 0x17, 0x1a, 0x13, 0x0d, 0xb7, 0xe5, 0x00, 0x11, 0x16, + 0x07, 0x0f, 0x0a, 0x09, 0x08, 0x0c, 0x1a, 0xce, 0x0b, 0x08, 0x00, 0x05, 0x1f, 0xab, 0x03, 0x02, 0x05, 0xa9, 0x15, + 0x0d, 0x16, 0x1d, 0x11, 0x0e, 0x2a, 0x18, 0x13, 0x03, 0x05, 0xe7, 0xcf, 0x1b, 0x02, 0xda, 0x0f, 0xca, 0xc4, 0x15, + 0x0c, 0x05, 0x1b, 0xa6, 0x0a, 0x13, 0x0d, 0x13, 0x0e, 0x0a, 0xbe, 0x01, 0x1c, 0x19, 0x29, 0xfe, 0xfb, 0x0c, 0x1b, + 0x15, 0x11, 0x12, 0x04, 0xb3, 0xb9, 0x07, 0x1b, 0x08, 0xd9, 0xd7, 0x10, 0x03, 0xf1, 0xd2, 0x13, 0x17, 0x37, 0x16, + 0xfe, 0xd7, 0x13, 0x27, 0x10, 0x06, 0x0b, 0x05, 0xbd, 0xfb, 0xe7, 0xf9, 0x0c, 0xc6, 0x13, 0x12, 0x1c, 0x0d, 0x07, + 0x05, 0x09, 0xd5, 0xde, 0x18, 0x16, 0x18, 0xf4, 0xe0, 0x2a, 0x13, 0x07, 0x12, 0x10, 0x05, 0x0a, 0x0f, 0x11, 0x0a, + 0xf6, 0xc5, 0x07, 0x05, 0x22, 0x0a, 0x93, 0xa4, 0x11, 0x1f, 0x1d, 0x11, 0x19, 0xf4, 0xd4, 0xc5, 0x16, 0x01, 0x10, + 0x16, 0x0c, 0x0f, 0x0e, 0x0d, 0x0a, 0x09, 0xc8, 0x27, 0xc4, 0x07, 0x22, 0x13, 0x13, 0x08, 0x04, 0x00, 0x01, 0xab, + 0xb2, 0x1f, 0x12, 0x1d, 0x0e, 0xde, 0x1d, 0x1e, 0x07, 0x0f, 0x0c, 0x0e, 0x0c, 0xd2, 0xef, 0x13, 0xf5, 0xc7, 0xd5, + 0x05, 0x09, 0xd7, 0xeb, 0x10, 0x00, 0x0a, 0x07, 0x12, 0x1c, 0x14, 0x13, 0x0a, 0x18, 0x07, 0x22, 0x00, 0x0a, 0x11, + 0x16, 0x0d, 0x00, 0x00, 0xf8, 0xc5, 0xb8, 0x16, 0x05, 0x05, 0x07, 0xa6, 0x0f, 0x15, 0x0d, 0x0e, 0x0c, 0xbe, 0x19, + 0x22, 0x0a, 0x0c, 0x10, 0x1c, 0x0e, 0x07, 0x0f, 0x07, 0x05, 0x97, 0x1d, 0x06, 0xe3, 0xde, 0x35, 0x15, 0x01, 0xa4, + 0x04, 0x07, 0x08, 0x07, 0xc9, 0xc7, 0x08, 0x1d, 0x22, 0xe1, 0xcd, 0x13, 0x0a, 0x0b, 0x2a, 0x07, 0x07, 0x11, 0x0f, + 0xd4, 0xd4, 0xed, 0x13, 0x08, 0x03, 0x00, 0x22, 0x06, 0x08, 0x0f, 0x18, 0x15, 0x16, 0x11, 0xf0, 0xdb, 0x1b, 0xff, + 0x11, 0x05, 0x0c, 0x12, 0x13, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x7d, 0x09, 0x0f, 0x07, + 0x0a, 0xb3, 0xbc, 0x13, 0x18, 0x19, 0x0e, 0x13, 0x11, 0x1b, 0x14, 0x0c, 0x0e, 0x08, 0x06, 0x03, 0x63, 0xd1, 0x2f, + 0x22, 0xd9, 0xf3, 0x0a, 0xfe, 0x1a, 0x01, 0x06, 0x0f, 0xc4, 0x0c, 0x16, 0x16, 0x1a, 0xcf, 0x14, 0x03, 0x1c, 0x19, + 0x0e, 0x16, 0x1f, 0x12, 0x04, 0x0d, 0xef, 0xa3, 0xde, 0x05, 0xfb, 0xb0, 0x0a, 0x0a, 0x0f, 0x10, 0x18, 0x14, 0x0f, + 0x04, 0x33, 0x18, 0x0a, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc6, 0x2c, 0x18, 0x18, 0x0d, 0x0a, + 0xa8, 0x05, 0x11, 0x0a, 0x09, 0xdc, 0xe1, 0x17, 0xbf, 0x13, 0x12, 0x11, 0xcf, 0x13, 0x18, 0x20, 0x13, 0x03, 0x05, + 0x02, 0x0a, 0x0e, 0x1b, 0xdc, 0xe3, 0x02, 0xb3, 0xde, 0x16, 0x10, 0x16, 0x20, 0x13, 0xc8, 0x1d, 0xf2, 0xde, 0xd9, + 0x0a, 0x1b, 0x13, 0x0e, 0x08, 0x11, 0x13, 0x11, 0x08, 0x84, 0x0a, 0x32, 0x0d, 0x0e, 0x0c, 0x00, 0x11, 0x02, 0x00, + 0x06, 0x0b, 0x08, 0x9d, 0xfd, 0x2e, 0x22, 0x1b, 0x1b, 0x0b, 0x0f, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xdd, 0xf4, 0xe0, 0x50, 0x00, 0x00, 0x1d, 0x04, 0xdf, 0x00, 0x06, 0x0d, 0x07, 0x0f, 0x15, 0x12, 0x04, 0x1b, + 0x0a, 0x1b, 0x11, 0x13, 0x15, 0xb8, 0xdc, 0x00, 0xde, 0x05, 0x06, 0x05, 0xfc, 0x04, 0x03, 0x0f, 0x13, 0x0c, 0x00, + 0xd4, 0x11, 0x20, 0x13, 0xfc, 0x1c, 0x11, 0x0c, 0x0b, 0x07, 0x04, 0x00, 0x0f, 0xcb, 0xd4, 0x11, 0x29, 0xcb, 0xf4, + 0xb5, 0xf4, 0x18, 0x15, 0x0f, 0x0c, 0x0a, 0x0a, 0x00, 0x1d, 0x09, 0xc1, 0x29, 0x0f, 0xc8, 0x03, 0x07, 0x25, 0x09, + 0x0e, 0xce, 0xdb, 0x0c, 0x11, 0x0d, 0x02, 0x03, 0xaf, 0xfb, 0x06, 0x06, 0x19, 0xcd, 0x1f, 0x12, 0x0b, 0xd7, 0xe1, + 0x24, 0x20, 0x0a, 0x07, 0x18, 0x0a, 0x04, 0x0d, 0x13, 0x13, 0x03, 0x0e, 0x19, 0x03, 0xe2, 0xe0, 0xae, 0x07, 0x11, + 0x07, 0x08, 0x09, 0x12, 0xdb, 0x7b, 0x1d, 0x1b, 0x00, 0x1c, 0x14, 0x0c, 0x0f, 0x11, 0x13, 0x11, 0xd0, 0xf1, 0xdb, + 0x14, 0x11, 0xfb, 0xb8, 0x0e, 0xed, 0xdd, 0x08, 0x20, 0x0e, 0x09, 0x0a, 0xfc, 0x1c, 0x12, 0x0e, 0x22, 0x0a, 0x07, + 0x07, 0x0c, 0x05, 0x0c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x05, 0xce, 0x52, 0xe1, 0x1a, 0x0e, 0xe3, 0xf5, 0x10, + 0x0d, 0x0c, 0x0a, 0x0b, 0x3b, 0x32, 0x06, 0x05, 0x0b, 0x0f, 0x07, 0x0a, 0xea, 0xdc, 0xf1, 0x98, 0x0e, 0x0c, 0x0b, + 0x10, 0x03, 0x07, 0x07, 0x0a, 0x11, 0x14, 0x10, 0x00, 0xcb, 0x00, 0x1d, 0xf9, 0xf8, 0xd3, 0x13, 0xd4, 0xf7, 0x21, + 0x1b, 0x05, 0x0e, 0x0f, 0x0e, 0x0b, 0x06, 0x00, 0x98, 0xb2, 0x14, 0x19, 0x0c, 0x05, 0x1c, 0x16, 0x08, 0x1a, 0xcb, + 0xed, 0x29, 0x16, 0x02, 0x0a, 0x0a, 0x10, 0x12, 0x00, 0xd8, 0x16, 0xdf, 0x04, 0x0f, 0x2e, 0x0e, 0xbc, 0xe1, 0x0a, + 0x0a, 0xc5, 0x07, 0x08, 0x04, 0x0f, 0xe0, 0xd3, 0x21, 0x22, 0x23, 0x0b, 0x00, 0x16, 0x0c, 0x1b, 0x0f, 0x07, 0xf9, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x56, 0xc5, 0x11, 0xd5, 0x0e, 0x25, 0x0b, 0x05, 0x11, 0xc6, 0x0e, 0x0d, 0xe8, 0x21, + 0x0a, 0x0d, 0x17, 0x14, 0x02, 0xbd, 0x2b, 0x1b, 0xdb, 0xc4, 0xf6, 0x0f, 0x0a, 0x00, 0x00, 0x0b, 0x0c, 0x11, 0x0a, + 0x07, 0xfe, 0x18, 0x12, 0x11, 0x37, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xb7, 0x5d, 0x20, 0x0c, 0xca, 0x14, 0x11, 0x10, 0x0a, 0x0d, 0x10, 0x0f, 0x20, 0x17, 0x11, 0xce, 0xe5, 0xf6, + 0xed, 0xd9, 0x08, 0x02, 0x09, 0xeb, 0x0c, 0x09, 0x00, 0x01, 0x05, 0x0c, 0x10, 0x14, 0x07, 0x03, 0x07, 0x29, 0x0a, + 0x7b, 0x0c, 0xf4, 0x10, 0x0f, 0x07, 0x13, 0x14, 0x0e, 0x11, 0x16, 0x0a, 0x0c, 0x0c, 0x0c, 0x17, 0x05, 0xb6, 0xac, + 0x04, 0x14, 0x09, 0x0a, 0x05, 0x00, 0x24, 0x11, 0xac, 0xf6, 0x18, 0x14, 0x11, 0x1c, 0x14, 0x0e, 0xce, 0x0c, 0x13, + 0x11, 0xd4, 0x0a, 0x0e, 0x03, 0xd5, 0xd4, 0x11, 0x9a, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x15, 0x14, 0x15, 0x16, 0x0c, + 0x11, 0x0f, 0x0e, 0x19, 0x0e, 0x08, 0x02, 0x00, 0x20, 0x13, 0xba, 0x00, 0x15, 0xce, 0xc5, 0xc6, 0x14, 0x11, 0x0c, + 0x10, 0x11, 0x0f, 0x07, 0xfe, 0xd9, 0x0a, 0x00, 0x1d, 0x11, 0x0e, 0x12, 0xcf, 0x00, 0x11, 0x1a, 0x0a, 0xdc, 0xf1, + 0xb3, 0x0f, 0x07, 0x05, 0x04, 0x11, 0x14, 0x09, 0x0a, 0x03, 0x1d, 0x05, 0x07, 0x15, 0x14, 0x02, 0x19, 0x03, 0x00, + 0xe0, 0xdd, 0xf4, 0x1b, 0x07, 0x0f, 0x0c, 0x03, 0x0c, 0xe5, 0x62, 0x0d, 0xb0, 0x00, 0x00, 0x04, 0x0f, 0x15, 0x0b, + 0x0b, 0xc6, 0x19, 0x16, 0x0e, 0x20, 0x11, 0x04, 0xe3, 0xea, 0x0f, 0x09, 0x23, 0xd7, 0xff, 0x14, 0xfd, 0x16, 0x07, + 0x0d, 0x0c, 0x04, 0x0c, 0x0b, 0x0b, 0x11, 0x11, 0x16, 0xe3, 0x89, 0xcb, 0x13, 0x27, 0x11, 0x16, 0x1a, 0x12, 0x10, + 0x12, 0x0e, 0x08, 0x0a, 0x00, 0x00, 0xe4, 0xd9, 0xfa, 0xbb, 0x11, 0xbf, 0xbf, 0x1a, 0x14, 0x00, 0x02, 0x13, 0x1d, + 0x0f, 0x11, 0x1f, 0x16, 0xed, 0xde, 0x14, 0x0e, 0x13, 0x0c, 0xbf, 0xc8, 0x0d, 0xf5, 0xc1, 0x03, 0xf2, 0x00, 0x00, + 0x13, 0x11, 0x11, 0x13, 0x0c, 0x16, 0x1b, 0xfd, 0x1b, 0x1b, 0x1a, 0x05, 0x01, 0x13, 0x05, 0x05, 0x0a, 0x00, 0x00, + 0x00, 0xfb, 0xd3, 0xa9, 0x0f, 0xfb, 0xc4, 0x21, 0x19, 0x0e, 0x0c, 0x0a, 0x03, 0x11, 0xe5, 0xcf, 0x00, 0x18, 0x23, + 0x02, 0xcb, 0x0e, 0xa8, 0xed, 0x19, 0xf6, 0xe5, 0x11, 0x0a, 0x0c, 0x0e, 0x01, 0x05, 0x0b, 0x16, 0x05, 0x05, 0x0c, + 0x00, 0x07, 0xbd, 0x21, 0x12, 0x0e, 0x14, 0x1c, 0x0f, 0x11, 0x11, 0x0c, 0x0a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8b, + 0xbe, 0x00, 0xfb, 0xda, 0x21, 0x12, 0x11, 0x13, 0x0c, 0x05, 0x1d, 0x0c, 0xa7, 0x15, 0x16, 0x11, 0xb7, 0x0a, 0x18, + 0x0c, 0x1b, 0x0e, 0xd7, 0xfe, 0x0c, 0x0a, 0x11, 0x02, 0x05, 0x0e, 0x0d, 0x09, 0xfb, 0x8f, 0xfb, 0x10, 0x08, 0x1d, + 0xbe, 0xd5, 0x1d, 0x22, 0x20, 0x10, 0x14, 0x0f, 0x0c, 0x0c, 0x10, 0x16, 0xbc, 0x00, 0x0c, 0x9f, 0x0b, 0x10, 0xeb, + 0xdb, 0x14, 0x02, 0x0e, 0x0a, 0x0c, 0x19, 0x1a, 0x05, 0xfe, 0x1b, 0x17, 0xcb, 0x0f, 0x15, 0x11, 0x0f, 0x14, 0x07, + 0xd4, 0x0c, 0x01, 0x47, 0xe1, 0x00, 0x06, 0x19, 0x11, 0x0e, 0x1b, 0x0c, 0x0c, 0x05, 0x16, 0x20, 0x0c, 0x09, 0x0c, + 0x14, 0x0f, 0xfb, 0x0a, 0xfd, 0x08, 0x86, 0x0e, 0x0f, 0x0e, 0x0b, 0xb9, 0xf2, 0x18, 0x0e, 0xef, 0xdf, 0x13, 0x09, + 0x00, 0xfe, 0x11, 0xdb, 0x08, 0x9d, 0x00, 0x1d, 0xe3, 0x0b, 0x16, 0x12, 0x11, 0x1c, 0x19, 0xf3, 0xed, 0x0c, 0x03, + 0xec, 0x14, 0x0e, 0x11, 0x07, 0x03, 0x0a, 0x13, 0x0f, 0x02, 0x0e, 0x20, 0x0c, 0xd4, 0xc7, 0x1a, 0x1f, 0x16, 0x12, + 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x22, 0x1b, 0x14, 0xe2, 0xe4, 0x0e, 0x02, 0xd9, 0xc2, 0x00, + 0x24, 0x0f, 0x10, 0x0f, 0xd2, 0x04, 0x16, 0x00, 0x11, 0x14, 0x05, 0x09, 0xd3, 0xc2, 0x0d, 0x00, 0x11, 0x11, 0x15, + 0x16, 0x08, 0x09, 0x08, 0x07, 0x0f, 0x13, 0x24, 0x0a, 0xcf, 0xa2, 0x22, 0x1b, 0x21, 0x17, 0x10, 0x1b, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x86, 0x1b, 0x1d, 0x08, 0xbe, 0xf2, 0x0e, 0x0f, 0x09, 0x11, 0x20, 0x09, 0x0a, 0x0e, + 0xe3, 0xe8, 0x27, 0x0e, 0x00, 0x0b, 0x04, 0x14, 0x92, 0x98, 0x19, 0xcd, 0x00, 0x00, 0x00, 0x04, 0x16, 0x0a, 0x0c, + 0x03, 0xfd, 0x13, 0x1e, 0xd2, 0x0e, 0x0f, 0x02, 0x13, 0x0f, 0x18, 0xf9, 0x18, 0x13, 0x11, 0x1b, 0x16, 0x03, 0xfd, + 0xea, 0xa9, 0x11, 0x1f, 0x0a, 0x0e, 0xce, 0xf6, 0x1d, 0x07, 0x0a, 0x22, 0x11, 0x03, 0xad, 0x78, 0xe6, 0x07, 0x2c, + 0x15, 0x18, 0x16, 0x0a, 0x18, 0xe1, 0xf1, 0x07, 0x0a, 0x0c, 0x14, 0x15, 0x05, 0xf0, 0x07, 0x05, 0xf6, 0x0a, 0xf1, + 0xc1, 0xe5, 0x19, 0x13, 0x0e, 0x14, 0x15, 0x16, 0x14, 0x0e, 0x08, 0x02, 0x0a, 0x05, 0xc1, 0x62, 0xe1, 0x00, 0x06, + 0x1e, 0x0f, 0x0e, 0xc8, 0xfe, 0x1d, 0x1a, 0x20, 0x1b, 0x02, 0x03, 0xf6, 0xb0, 0x1b, 0x11, 0x10, 0x0a, 0x24, 0x19, + 0x15, 0x0b, 0xc3, 0x05, 0x10, 0x11, 0xeb, 0xc0, 0x17, 0x0e, 0x0c, 0x05, 0x07, 0x0a, 0x09, 0x25, 0x0f, 0x04, 0xde, + 0xcd, 0x00, 0x19, 0x18, 0x24, 0x16, 0x06, 0x00, 0x00, 0x00, 0xdd, 0xc6, 0xd0, 0xd1, 0x1e, 0x10, 0x0d, 0xfb, 0x07, + 0xc3, 0xfb, 0x03, 0x0e, 0x19, 0xc6, 0x15, 0x0f, 0xc3, 0x0c, 0x08, 0x18, 0x1a, 0x11, 0x14, 0x16, 0x15, 0xed, 0xc8, + 0xa0, 0x00, 0x00, 0x07, 0x1d, 0x0f, 0x0c, 0x10, 0x16, 0x19, 0x0e, 0x13, 0x22, 0x0a, 0x0a, 0x0a, 0x04, 0x9d, 0x0c, + 0x16, 0x1f, 0x0c, 0x14, 0x0f, 0x05, 0x02, 0x08, 0x00, 0xbd, 0x05, 0x16, 0x0c, 0x0d, 0x07, 0x05, 0xc0, 0xf2, 0xfd, + 0x25, 0x02, 0xcb, 0xc3, 0xa0, 0x00, 0x00, 0x00, 0x09, 0x25, 0x13, 0x0e, 0x11, 0x03, 0xc1, 0xdc, 0x07, 0x18, 0x0f, + 0x11, 0x04, 0xfb, 0x03, 0xfd, 0x16, 0x11, 0x0f, 0x24, 0x0f, 0x05, 0x05, 0x07, 0xf8, 0x0d, 0x18, 0x18, 0x12, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x20, 0x20, 0x4b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x20, 0x57, 0x72, + 0x61, 0x69, 0x74, 0x68, 0x20, 0x2e, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x06, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, + 0xc4, 0xfa, 0x39, 0xfd, 0x37, 0xf9, 0x00, 0xe3, 0xf0, 0xef, 0xee, 0xef, 0xe6, 0x13, 0x2c, 0xed, 0x17, 0x34, 0x3f, + 0x0c, 0xf6, 0xe8, 0xea, 0xf1, 0xea, 0xde, 0x40, 0x1d, 0xf6, 0xf4, 0xf4, 0xf3, 0xed, 0xea, 0xf0, 0xf3, 0xfc, 0x6d, + 0xf3, 0xdc, 0x0c, 0x1e, 0xf5, 0xfc, 0xf9, 0xf8, 0xf1, 0xf9, 0x3d, 0x1b, 0x15, 0xf7, 0xf1, 0xf2, 0xf3, 0xf0, 0xdd, + 0xdc, 0xf6, 0x05, 0xf4, 0xef, 0xf2, 0xe5, 0xf7, 0x04, 0x35, 0x3d, 0xf6, 0xf4, 0x51, 0xe9, 0xef, 0xe9, 0xe3, 0x13, + 0x22, 0xf3, 0xef, 0xf0, 0xf3, 0xfb, 0xf2, 0x0f, 0x22, 0xea, 0xf4, 0xf3, 0xe6, 0x3c, 0xea, 0xef, 0xf2, 0xed, 0x27, + 0xfd, 0xea, 0xf4, 0xf9, 0x3c, 0x3a, 0x2a, 0xef, 0x0c, 0x11, 0xef, 0xe8, 0x0f, 0x09, 0xf9, 0xec, 0x00, 0x53, 0xf4, + 0xf4, 0xf4, 0xea, 0xf6, 0xf4, 0xf8, 0x28, 0xf6, 0xe7, 0x20, 0x3a, 0xf1, 0xf7, 0xf1, 0xed, 0x1d, 0x16, 0xe8, 0xf1, + 0xf9, 0xf6, 0xe1, 0xef, 0xef, 0xf3, 0x00, 0xf0, 0xf3, 0xef, 0xe3, 0xfb, 0xfe, 0xef, 0xf2, 0x1f, 0xef, 0xf2, 0x00, + 0x1a, 0xf4, 0xf2, 0x00, 0x26, 0x22, 0x02, 0xeb, 0xf4, 0xf4, 0xe5, 0x27, 0x8f, 0x04, 0xf7, 0xe1, 0xee, 0xeb, 0xe8, + 0xfa, 0xf9, 0x38, 0xfd, 0xf4, 0x51, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xec, 0xed, 0xf1, 0x1d, 0xf2, + 0xf1, 0xf2, 0xee, 0x33, 0x00, 0xf2, 0xe8, 0xfa, 0x00, 0xe8, 0xe6, 0x13, 0x14, 0xf4, 0xfa, 0xf9, 0xea, 0xf0, 0xff, + 0xed, 0xdc, 0x24, 0x07, 0xef, 0xf2, 0x1f, 0x0c, 0xf4, 0xf9, 0x02, 0xf2, 0xe5, 0xeb, 0xef, 0x00, 0x00, 0x0e, 0x27, + 0x4d, 0xef, 0x29, 0x16, 0xef, 0xea, 0xf4, 0x0c, 0x34, 0xf3, 0xea, 0xed, 0x4c, 0xf6, 0xf4, 0x30, 0xf6, 0x05, 0xfe, + 0xd9, 0xe5, 0xe5, 0xe8, 0xf4, 0xf4, 0xf1, 0xeb, 0x30, 0xfc, 0x3e, 0xf0, 0xfd, 0x13, 0x28, 0xf1, 0xdc, 0xe9, 0x2a, + 0xfd, 0xea, 0x1d, 0xf5, 0xf4, 0xfb, 0xf3, 0xea, 0xef, 0xf2, 0xe8, 0xe8, 0x1f, 0x5f, 0x10, 0xed, 0xf6, 0xf5, 0x46, + 0x00, 0xfb, 0xf8, 0xf0, 0xe8, 0xea, 0x61, 0x07, 0xf4, 0xf6, 0xe1, 0xef, 0xfb, 0xf9, 0xff, 0xf0, 0xf1, 0xe7, 0xdc, + 0x4b, 0x05, 0xf2, 0xed, 0xfa, 0x2f, 0xe8, 0xdd, 0xed, 0xea, 0xe6, 0xfd, 0x3c, 0xeb, 0xec, 0x34, 0x00, 0x2e, 0x0c, + 0x24, 0xfd, 0x01, 0x02, 0xe0, 0xeb, 0xe8, 0xde, 0xf1, 0x18, 0x1f, 0xfc, 0xec, 0xea, 0x33, 0x1e, 0x04, 0xeb, 0x35, + 0x4c, 0xf0, 0xf4, 0xf0, 0xea, 0xe3, 0x04, 0x12, 0xf1, 0xf1, 0xef, 0xea, 0x00, 0x5d, 0xee, 0xf4, 0x01, 0xee, 0xfc, + 0xf4, 0x11, 0x10, 0xeb, 0xf4, 0xfd, 0xe8, 0x30, 0x0f, 0xed, 0xf4, 0xf5, 0x3e, 0xe0, 0xf1, 0xef, 0xeb, 0xf6, 0x00, + 0xf3, 0xf2, 0xf1, 0xda, 0x02, 0x41, 0x2e, 0xf9, 0xf7, 0xec, 0x03, 0x3c, 0xef, 0xed, 0xe8, 0xf8, 0x40, 0xf4, 0xec, + 0xf1, 0xea, 0xe8, 0x2f, 0xfb, 0xff, 0x58, 0xef, 0xec, 0xe8, 0xe6, 0xe0, 0xf7, 0xfa, 0xf7, 0xf1, 0xef, 0x20, 0xea, + 0x53, 0x39, 0xed, 0xea, 0x3a, 0xf7, 0xf1, 0xea, 0xeb, 0x38, 0xfb, 0x1d, 0xe8, 0xe9, 0x23, 0x24, 0xf9, 0xef, 0xef, + 0xe0, 0xf6, 0x3b, 0xf6, 0xf9, 0xec, 0xea, 0x42, 0x13, 0xf9, 0xf7, 0x15, 0x16, 0xf9, 0xf6, 0xf6, 0xf7, 0xf6, 0xe1, + 0xea, 0xee, 0xf4, 0xfa, 0xe9, 0xe3, 0xf4, 0xe3, 0xf4, 0xf4, 0xfe, 0x00, 0x3c, 0xfd, 0x08, 0xf4, 0xea, 0xe8, 0xf9, + 0x00, 0x2b, 0xef, 0xed, 0xf9, 0x00, 0x1d, 0xb6, 0xf4, 0xf6, 0x00, 0x07, 0xec, 0xe8, 0xeb, 0xde, 0xfa, 0x3d, 0xf1, + 0xf5, 0xee, 0x0b, 0x4b, 0x3d, 0x00, 0x00, 0xe9, 0xe8, 0x2f, 0xfb, 0xf1, 0xf4, 0xea, 0xef, 0x1b, 0xfb, 0xe8, 0x2b, + 0x00, 0xf4, 0xf4, 0xf3, 0xef, 0x01, 0xe8, 0xf3, 0xf0, 0xea, 0x13, 0xf4, 0xfd, 0xf6, 0xf4, 0xf2, 0xf4, 0xe8, 0x44, + 0x16, 0xe4, 0xf2, 0x31, 0xea, 0xf3, 0xf9, 0xfb, 0xef, 0xeb, 0xec, 0xeb, 0x00, 0x43, 0x4c, 0xfa, 0x03, 0x00, 0xe8, + 0x33, 0x09, 0xef, 0xea, 0xf0, 0x44, 0xef, 0xec, 0xe8, 0x02, 0x66, 0x17, 0xfb, 0xee, 0xe1, 0xe8, 0xef, 0xfa, 0xef, + 0xe8, 0xfb, 0xf9, 0xf6, 0xef, 0xeb, 0x3d, 0x2e, 0x04, 0x00, 0xef, 0xed, 0xf1, 0xe8, 0x2a, 0xf1, 0xec, 0xe3, 0xf2, + 0x44, 0x16, 0xf3, 0xf0, 0xea, 0x2b, 0x2f, 0xe2, 0xd5, 0x2d, 0x05, 0xfc, 0xff, 0xf2, 0xed, 0xf9, 0x44, 0xf5, 0xef, + 0xf4, 0x6b, 0x06, 0x00, 0x00, 0xfa, 0xf6, 0xe8, 0xed, 0xef, 0xf1, 0xeb, 0xee, 0xeb, 0xf4, 0xe5, 0xf4, 0x4b, 0xf7, + 0xfa, 0xd7, 0xe5, 0x11, 0x0a, 0xf4, 0xea, 0xed, 0xef, 0x4b, 0xf1, 0xe3, 0xf2, 0x41, 0x38, 0x03, 0x38, 0xf5, 0xf4, + 0xf0, 0xe0, 0xf4, 0xe8, 0xcf, 0x1f, 0x22, 0xf9, 0xfb, 0xfb, 0xef, 0x0f, 0x8f, 0x17, 0xdd, 0xe1, 0xef, 0xf4, 0x0c, + 0x24, 0xed, 0xee, 0xe9, 0xee, 0x22, 0xe8, 0x00, 0x61, 0x00, 0xfe, 0xf1, 0xeb, 0x07, 0xea, 0xef, 0xec, 0xea, 0xef, + 0x27, 0xef, 0xf5, 0xe5, 0xf8, 0x57, 0xf5, 0xee, 0xf0, 0xf6, 0xf2, 0xee, 0xf9, 0x33, 0xfd, 0xf5, 0xef, 0xef, 0xe5, + 0xea, 0x49, 0x2c, 0xf5, 0xf9, 0xf7, 0xf3, 0xf4, 0xfc, 0x24, 0xe8, 0xe8, 0xf3, 0x4c, 0xf8, 0xed, 0xec, 0x0c, 0x83, + 0x0a, 0xe1, 0xd9, 0xec, 0xef, 0xf5, 0xf4, 0xfa, 0xde, 0xf9, 0xf4, 0xf4, 0xef, 0xef, 0x53, 0x3a, 0x2e, 0xf3, 0xef, + 0xef, 0xfa, 0xe5, 0xe3, 0x1b, 0x0c, 0xf1, 0xf2, 0xe4, 0x17, 0x43, 0xeb, 0x4d, 0x00, 0xe0, 0xe3, 0xf0, 0x3a, 0xf9, + 0xf6, 0xfe, 0xf6, 0xf4, 0xee, 0x45, 0xe9, 0x20, 0x1e, 0xff, 0xf6, 0xfc, 0xf6, 0xf4, 0xfe, 0xd9, 0xe7, 0xe6, 0xf4, + 0xff, 0xf4, 0xf0, 0xec, 0xe8, 0x49, 0xf9, 0xef, 0xd8, 0xf2, 0xf4, 0xf4, 0x1a, 0xfe, 0xe1, 0x00, 0x00, 0x11, 0xfd, + 0xf2, 0x00, 0x9b, 0x21, 0xf4, 0xe8, 0x07, 0x2a, 0xf9, 0xe2, 0xe8, 0xeb, 0xe9, 0x40, 0xf8, 0xf6, 0xfe, 0xf4, 0xec, + 0x4a, 0x24, 0x25, 0xee, 0xf2, 0xf1, 0xf4, 0xf4, 0xec, 0x31, 0x00, 0xef, 0xe3, 0xe8, 0x5e, 0x0a, 0xf4, 0xf4, 0xf4, + 0xef, 0xe5, 0xf9, 0xe0, 0xe8, 0xf3, 0xfa, 0xfa, 0xf2, 0x2b, 0xe4, 0x3f, 0xfd, 0xf7, 0xef, 0xf6, 0xf8, 0xf5, 0xf8, + 0xef, 0xea, 0xe8, 0x0f, 0x2b, 0xf4, 0xe8, 0xea, 0x27, 0x83, 0xf9, 0xf6, 0xf8, 0xfb, 0xf2, 0xf6, 0xdf, 0x4b, 0xec, + 0xeb, 0xe9, 0x34, 0x04, 0xef, 0xed, 0x30, 0x4e, 0xfb, 0xe6, 0xf1, 0xef, 0xf2, 0xf3, 0xf6, 0xf5, 0xee, 0xf4, 0xeb, + 0xf1, 0xf7, 0x48, 0xfb, 0xf0, 0x12, 0x1e, 0xd9, 0xe1, 0xfa, 0xe8, 0xf2, 0xef, 0xfb, 0x3c, 0xef, 0xe6, 0x2c, 0x2b, + 0x18, 0x28, 0xe4, 0xe9, 0xe9, 0x2a, 0x04, 0xf0, 0xf4, 0xfd, 0xf4, 0xf2, 0xee, 0x23, 0x33, 0x49, 0x00, 0x00, 0x00, + 0x00, 0xfb, 0xf3, 0x00, 0xe3, 0xed, 0xf4, 0xf6, 0xf4, 0xec, 0xed, 0xf1, 0xe5, 0xe1, 0x24, 0x0d, 0xf4, 0xf3, 0xf4, + 0xef, 0xf2, 0x26, 0xf7, 0xdc, 0xef, 0x21, 0x0c, 0xf7, 0x4e, 0x32, 0xf7, 0xf3, 0xe3, 0xe3, 0xed, 0x27, 0x0a, 0xea, + 0xf3, 0x22, 0x11, 0xf2, 0x26, 0x28, 0xee, 0x06, 0xe5, 0xf4, 0x54, 0xf4, 0xe1, 0xef, 0xf3, 0xf4, 0xf0, 0xef, 0xfb, + 0x38, 0xe9, 0x05, 0x70, 0x01, 0x00, 0x00, 0xf0, 0xf2, 0xde, 0xfe, 0xee, 0xf5, 0xf3, 0xef, 0xf0, 0xee, 0xf4, 0x25, + 0xec, 0xe3, 0x13, 0x2c, 0xf9, 0xf9, 0xf8, 0xf7, 0xf8, 0xed, 0xef, 0xf9, 0xea, 0x18, 0x0a, 0xfd, 0x50, 0x11, 0xf5, + 0xea, 0xee, 0xf5, 0xf4, 0x00, 0xe0, 0x27, 0x2b, 0xea, 0xcd, 0x44, 0x55, 0xe1, 0x29, 0x1d, 0xe1, 0xea, 0xef, 0xf8, + 0xf0, 0xef, 0xf4, 0xf6, 0xf3, 0xe3, 0xfe, 0xfd, 0xef, 0x5a, 0x1e, 0xf6, 0xf4, 0xf4, 0x11, 0x07, 0xec, 0x00, 0xed, + 0xed, 0xf3, 0xed, 0xea, 0xfe, 0x1b, 0xe7, 0xfe, 0x13, 0xf9, 0x6f, 0x00, 0x06, 0x1d, 0xf6, 0xf9, 0xf6, 0xfb, 0xf1, + 0xef, 0xef, 0xf2, 0x79, 0x12, 0x00, 0xdd, 0xed, 0xf6, 0xfe, 0xf9, 0xfd, 0xec, 0xfb, 0xf5, 0xf4, 0xfa, 0x3f, 0xe8, + 0xf4, 0xfc, 0xd1, 0xe8, 0xef, 0xf1, 0xf4, 0xf2, 0xf3, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x6d, 0x3d, 0xf9, + 0xf1, 0xec, 0xea, 0xf7, 0xfe, 0x00, 0xdd, 0x27, 0x0c, 0x28, 0xe9, 0xfb, 0xf4, 0xf5, 0x09, 0xdc, 0xfd, 0x46, 0x31, + 0x13, 0xf7, 0xef, 0xed, 0xfb, 0xef, 0xe8, 0xea, 0xe8, 0x17, 0x51, 0x05, 0x0c, 0x02, 0xf2, 0xef, 0xef, 0xdd, 0x06, + 0xf3, 0xfb, 0xef, 0xea, 0x44, 0xed, 0xf1, 0x03, 0x2b, 0xe9, 0xe3, 0xe5, 0xf9, 0xfa, 0xf9, 0xf1, 0xf2, 0xf6, 0xfe, + 0xfb, 0xf4, 0xf2, 0x15, 0x85, 0x42, 0xe1, 0xef, 0xf3, 0xf9, 0x00, 0xf4, 0x00, 0xe1, 0xee, 0x45, 0xec, 0xe6, 0x0e, + 0x14, 0x0c, 0x24, 0xdc, 0xf4, 0x4d, 0xf6, 0xf9, 0xf7, 0xf6, 0xf9, 0xf1, 0xec, 0xe1, 0xec, 0xf5, 0xfb, 0x3c, 0xf4, + 0xf2, 0xef, 0xfb, 0xf1, 0x19, 0x0c, 0x0b, 0xe9, 0xea, 0xe5, 0x38, 0xf8, 0xea, 0xe8, 0x40, 0xef, 0xee, 0x18, 0xe9, + 0xe9, 0x84, 0xee, 0xef, 0x00, 0xfc, 0xfd, 0xf6, 0xf0, 0xef, 0x68, 0x2a, 0x00, 0x00, 0x00, 0xfa, 0xf6, 0xf4, 0xf9, + 0x05, 0xe8, 0xf4, 0xea, 0xfd, 0xf4, 0xf1, 0xee, 0xfb, 0xdb, 0xd7, 0xed, 0x4f, 0xf4, 0xf4, 0xf4, 0xf1, 0xf0, 0xe9, + 0xfa, 0x15, 0xf1, 0x0b, 0x18, 0x63, 0x07, 0xf0, 0xf4, 0xf5, 0xf5, 0xf4, 0xf8, 0x08, 0xee, 0xda, 0x65, 0x61, 0xed, + 0xf2, 0xfd, 0x05, 0xec, 0xef, 0xef, 0xfb, 0xfa, 0x46, 0xf3, 0x00, 0x00, 0xe4, 0xee, 0xeb, 0xe8, 0x10, 0x53, 0xf2, + 0x35, 0xf6, 0x1e, 0x00, 0xf0, 0xf2, 0xe6, 0x00, 0xe9, 0xeb, 0xf1, 0xf1, 0xf0, 0xef, 0x00, 0xee, 0xf9, 0x11, 0xea, + 0x4e, 0xf1, 0xf0, 0xf4, 0xff, 0xf5, 0xe7, 0xe5, 0x00, 0xf9, 0xe6, 0x00, 0x54, 0x0d, 0x2b, 0xf7, 0xf6, 0xf8, 0xf7, + 0xf8, 0x06, 0xd6, 0x05, 0x77, 0x04, 0xe4, 0x04, 0x49, 0x12, 0xe7, 0xef, 0xf4, 0xf6, 0xf4, 0xf9, 0x00, 0xf8, 0xf7, + 0xf3, 0xf4, 0xea, 0xd8, 0x5b, 0x11, 0xfb, 0xf9, 0xfb, 0xf5, 0xff, 0xf6, 0xe9, 0x26, 0x13, 0xe9, 0xec, 0xdc, 0xec, + 0xed, 0xef, 0xfd, 0xdf, 0x00, 0x11, 0xfd, 0x58, 0x23, 0x22, 0xe4, 0x3a, 0xf3, 0xe8, 0xfc, 0xfa, 0xed, 0xea, 0x0f, + 0x33, 0x46, 0xf4, 0xf9, 0xf9, 0xf1, 0xe0, 0xf7, 0x00, 0xf9, 0x3f, 0xf4, 0xfd, 0xef, 0xf9, 0xf4, 0xe8, 0xef, 0xde, + 0xf3, 0xea, 0xf7, 0xf8, 0xf2, 0xef, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x60, 0x51, 0x22, 0xec, 0xf7, 0xfa, 0xf0, 0xef, + 0xf1, 0xf4, 0x09, 0xe8, 0x00, 0x2e, 0xe4, 0xde, 0x4f, 0xeb, 0xef, 0xfb, 0xed, 0xe9, 0x3d, 0x0f, 0x48, 0x08, 0xf1, + 0xed, 0xef, 0xe8, 0xde, 0xee, 0xed, 0x2e, 0x0c, 0xef, 0x05, 0x29, 0x1e, 0xf4, 0xf1, 0xe0, 0x00, 0x44, 0xf2, 0xef, + 0xef, 0xed, 0x10, 0xef, 0xea, 0xe4, 0x11, 0x0c, 0xf6, 0xfe, 0xea, 0xec, 0xf1, 0xfc, 0xea, 0xef, 0xf2, 0x35, 0x30, + 0x00, 0x46, 0xf4, 0xda, 0xf9, 0x35, 0xf3, 0xf2, 0xf2, 0x04, 0xea, 0xe8, 0x05, 0x33, 0xe5, 0x01, 0x68, 0xfd, 0xe5, + 0xe4, 0xec, 0x25, 0x2b, 0xf9, 0xf2, 0xec, 0xed, 0xf4, 0xef, 0xee, 0xdf, 0xf1, 0x3f, 0xfd, 0xfa, 0xfa, 0xfb, 0xfc, + 0xf1, 0xe3, 0xef, 0x9e, 0xf6, 0xed, 0xec, 0xe1, 0xf9, 0xf6, 0xe5, 0xe8, 0xe8, 0xe9, 0x12, 0x43, 0x45, 0xf8, 0xe6, + 0xe7, 0xfb, 0x33, 0xef, 0xf2, 0x74, 0x03, 0xfb, 0xef, 0x2a, 0x00, 0x00, 0x00, 0xf8, 0xf1, 0xe8, 0x00, 0xec, 0xf5, + 0xf3, 0xf4, 0x00, 0xeb, 0xef, 0xf3, 0xef, 0xdc, 0xe5, 0x11, 0x33, 0xea, 0xf2, 0xec, 0xf2, 0xed, 0x00, 0x00, 0x00, + 0x00, 0xb8, 0xf8, 0xf7, 0xed, 0xee, 0xea, 0xde, 0xf2, 0x52, 0x16, 0xe8, 0x36, 0xfa, 0xe8, 0xfc, 0xe2, 0xfc, 0x2e, + 0xf8, 0x00, 0xfb, 0xf9, 0xeb, 0x15, 0x31, 0xf3, 0xeb, 0xf3, 0xe8, 0x16, 0x50, 0xf9, 0xf4, 0xf4, 0xed, 0xe9, 0x07, + 0x01, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, + 0x00, 0x40, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x1e, 0x00, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x0a, 0x00, 0x28, 0x00, 0x1e, 0x00, 0x18, 0x00, 0x32, 0x00, + 0x20, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x46, 0x00, 0x20, 0x00, 0x50, 0x00, 0x20, 0x00, 0x5a, 0x00, 0x20, 0x00, 0x64, + 0x00, 0x20, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x78, 0x00, 0x20, 0x00, 0x82, 0x00, 0x20, 0x00, 0x03, 0x06, 0x01, 0x01, + 0x01, 0x02, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x07, 0x00, 0x00, + 0x70, 0x03, 0x00, 0x00, 0x86, 0x04, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x05, + 0x03, 0x05, 0x02, 0xe8, 0x22, 0xe2, 0xf7, 0xfd, 0xfb, 0xfb, 0xfd, 0xf9, 0x6b, 0xd3, 0xef, 0xfe, 0x02, 0x05, 0x03, + 0x09, 0xa6, 0x3d, 0x0e, 0x08, 0x0a, 0x07, 0x08, 0x0e, 0x44, 0xfe, 0x05, 0x0a, 0x04, 0x00, 0x05, 0x06, 0x8b, 0x33, + 0x01, 0xfb, 0xfb, 0xfb, 0xf8, 0xf4, 0xd8, 0xf9, 0xfd, 0xfb, 0xf4, 0x07, 0x07, 0x05, 0x0d, 0x22, 0xf4, 0x03, 0x02, + 0x05, 0x05, 0x03, 0xe5, 0xff, 0x11, 0x01, 0x04, 0xeb, 0xfa, 0xf6, 0x10, 0x8a, 0xb4, 0xf5, 0xf9, 0xf8, 0xf9, 0xf4, + 0xd0, 0xd8, 0x1e, 0xfe, 0xfe, 0xff, 0x00, 0x0f, 0x08, 0x4a, 0xe5, 0x08, 0x09, 0x06, 0x0a, 0x0a, 0x09, 0xfe, 0x0d, + 0x0a, 0xec, 0xfd, 0xfd, 0xfe, 0xfb, 0xdf, 0x0d, 0xf9, 0xfd, 0xf9, 0xfb, 0xfb, 0xfd, 0xca, 0x11, 0x0d, 0x0e, 0x01, + 0x02, 0x00, 0x00, 0x83, 0xcf, 0x03, 0x04, 0x06, 0x07, 0x07, 0x06, 0xe6, 0x0b, 0xfb, 0xf5, 0xf6, 0xf9, 0xf6, 0xf9, + 0x07, 0xf4, 0xf6, 0xf6, 0xfa, 0xf6, 0xf4, 0x07, 0x80, 0x29, 0x05, 0xf9, 0x00, 0x05, 0x02, 0x03, 0x57, 0x21, 0xe6, + 0x08, 0x07, 0x0d, 0x05, 0x08, 0x80, 0x23, 0x05, 0xf9, 0xf8, 0xfb, 0xf9, 0xfe, 0x1d, 0x0d, 0xea, 0xfa, 0xfc, 0xfa, + 0xfc, 0xfb, 0x0f, 0x1b, 0xfe, 0x05, 0x09, 0x08, 0x09, 0x08, 0x17, 0x23, 0xfb, 0x05, 0xfd, 0x02, 0x01, 0x04, 0x00, + 0x3e, 0x53, 0xfb, 0xfa, 0xf4, 0xf8, 0xf6, 0xf2, 0xc9, 0x90, 0xef, 0xf8, 0xfb, 0xfe, 0x07, 0x08, 0xd0, 0x1e, 0x05, + 0x05, 0x00, 0x06, 0x05, 0x05, 0xad, 0x32, 0x05, 0x05, 0x00, 0x00, 0xf4, 0xf6, 0x6b, 0xc6, 0xf6, 0xfc, 0x00, 0xfa, + 0xfc, 0x00, 0x9f, 0x06, 0x01, 0xf9, 0x00, 0x04, 0x08, 0x07, 0x0a, 0x05, 0x07, 0x03, 0x0a, 0x08, 0x07, 0x07, 0x55, + 0xec, 0xf6, 0x02, 0x03, 0x05, 0x03, 0x04, 0x1f, 0x16, 0xe7, 0xfb, 0xfd, 0xfc, 0xfa, 0xf9, 0x8d, 0x24, 0x05, 0xf6, + 0x27, 0x0b, 0x60, 0x45, 0x37, 0x03, 0x2a, 0xf9, 0xd1, 0x8d, 0xbb, 0xf5, 0x30, 0x02, 0x30, 0x75, 0x68, 0x16, 0xd4, + 0xe6, 0x9f, 0xe3, 0x6b, 0x1e, 0xa1, 0x0a, 0xf4, 0x56, 0x05, 0x0a, 0x01, 0x18, 0x08, 0xf3, 0xef, 0xd6, 0xef, 0xee, + 0xd8, 0x70, 0xe4, 0x1f, 0x77, 0x79, 0x41, 0x98, 0x36, 0x3f, 0x0f, 0xb3, 0xe7, 0x39, 0xd0, 0x8e, 0x2f, 0x03, 0x16, + 0x95, 0xcc, 0xb3, 0x0f, 0xf8, 0x00, 0x7a, 0xa0, 0xa4, 0x92, 0xc2, 0xec, 0xf4, 0xef, 0x07, 0x46, 0x8f, 0x17, 0x39, + 0x26, 0x46, 0x29, 0xb3, 0xcf, 0x95, 0x4f, 0x1e, 0x92, 0x10, 0x23, 0x1f, 0x21, 0x1e, 0x5e, 0x7a, 0xf3, 0x3f, 0xa9, + 0xdd, 0x87, 0x45, 0x1e, 0x40, 0x0a, 0x0f, 0xd1, 0x13, 0x0f, 0xf2, 0xf1, 0x0c, 0xd1, 0x5e, 0xcf, 0xa9, 0x56, 0xf4, + 0x48, 0x87, 0x1d, 0x70, 0x75, 0x34, 0x3a, 0xce, 0x22, 0xd9, 0x7c, 0xc4, 0xc2, 0xba, 0x1c, 0x28, 0x55, 0xb2, 0x03, + 0xd3, 0x2c, 0xf2, 0xda, 0x3c, 0x2b, 0xba, 0x07, 0x62, 0xaf, 0xf7, 0xf4, 0x04, 0xf7, 0x00, 0xf3, 0x5c, 0x25, 0xcf, + 0x14, 0xd3, 0x55, 0xec, 0xf4, 0xce, 0xf5, 0xcc, 0x67, 0x7b, 0xe8, 0x7c, 0xe7, 0x02, 0x30, 0xe7, 0x0d, 0xa5, 0x3f, + 0x23, 0xa5, 0x15, 0xf8, 0x41, 0xb7, 0xd3, 0xc0, 0xac, 0x10, 0xa8, 0x37, 0x0a, 0xf4, 0x1e, 0xee, 0x2d, 0xc6, 0xef, + 0xc1, 0x56, 0xd9, 0xec, 0xf4, 0x08, 0x35, 0xd5, 0x16, 0x50, 0x01, 0xf3, 0x5d, 0x58, 0x37, 0x5c, 0x74, 0xf6, 0xcc, + 0x1e, 0x04, 0xa7, 0x70, 0x14, 0x42, 0xfd, 0x11, 0xc0, 0xd4, 0x0f, 0x3d, 0xb4, 0xe2, 0xb7, 0x6c, 0xde, 0xee, 0x34, + 0x18, 0x4f, 0x76, 0x28, 0xde, 0x2d, 0xfb, 0xbc, 0x74, 0xb7, 0xda, 0xf3, 0x1c, 0x19, 0x11, 0x17, 0x19, 0x00, 0xfc, + 0x49, 0x4f, 0x1a, 0xf8, 0x60, 0xd7, 0x82, 0x79, 0xe0, 0xbc, 0x2f, 0x0b, 0xf0, 0xc0, 0xb9, 0x8d, 0x02, 0x2d, 0x4b, + 0x8b, 0x1e, 0x14, 0xd5, 0x38, 0x41, 0x8e, 0x30, 0xe9, 0x8e, 0xbb, 0xe0, 0xdc, 0x0b, 0x3e, 0xbd, 0xd0, 0xcb, 0xd4, + 0xa3, 0xa7, 0x47, 0x26, 0x1e, 0xfa, 0x06, 0xe4, 0x08, 0xfa, 0xfb, 0x03, 0xf4, 0xdc, 0x14, 0xfc, 0xff, 0xc6, 0x10, + 0xfb, 0xf8, 0x51, 0xcf, 0xfc, 0x02, 0x58, 0xd8, 0xfb, 0xfe, 0xe9, 0x9b, 0x3a, 0x03, 0x05, 0x5d, 0xd3, 0xff, 0x06, + 0x50, 0xdc, 0x05, 0x08, 0x61, 0x4a, 0x02, 0xf9, 0x48, 0xd6, 0xf6, 0xff, 0xfb, 0xc2, 0x19, 0xfd, 0xfe, 0x0d, 0xf1, + 0xff, 0xfe, 0x34, 0xe3, 0xff, 0x00, 0x03, 0xfe, 0x07, 0x03, 0xfa, 0x08, 0x05, 0x03, 0x00, 0x4b, 0xe4, 0x05, 0x08, + 0x55, 0x5b, 0x0a, 0x00, 0x78, 0xbf, 0xfb, 0x00, 0x26, 0xec, 0xff, 0xfc, 0x00, 0xff, 0x00, 0xfe, 0x00, 0x05, 0xf8, + 0x00, 0x01, 0xb9, 0x1c, 0x04, 0x06, 0xa7, 0x2b, 0x06, 0x00, 0x25, 0xf8, 0xfc, 0x02, 0x19, 0x06, 0xfb, 0x00, 0x04, + 0x53, 0xd3, 0xfe, 0x04, 0xb8, 0x25, 0x03, 0xfe, 0xb4, 0x11, 0x05, 0xfe, 0x56, 0x04, 0xe3, 0xfa, 0x00, 0xfe, 0xfe, + 0xfb, 0xff, 0x94, 0x2d, 0x00, 0x03, 0x28, 0xee, 0xfe, 0x00, 0xd5, 0x05, 0x0b, 0x00, 0x0e, 0x05, 0xfb, 0x05, 0x03, + 0x0c, 0xfb, 0x03, 0x02, 0xf2, 0xff, 0x00, 0xfb, 0xfe, 0xfe, 0xfb, 0xfd, 0x03, 0x00, 0xfa, 0xfc, 0xf6, 0xe6, 0x0a, + 0x01, 0xff, 0xdf, 0x10, 0x00, 0x02, 0x32, 0xf2, 0x00, 0x02, 0x17, 0x09, 0xfb, 0x08, 0x08, 0x12, 0xfc, 0x06, 0x02, + 0xd1, 0x22, 0x01, 0x07, 0xdb, 0x14, 0xfb, 0xff, 0x4f, 0xd5, 0x00, 0xfe, 0xf2, 0xf1, 0x0a, 0xfe, 0x02, 0xef, 0x05, + 0x00, 0xfe, 0x11, 0xf4, 0xfd, 0x07, 0x61, 0xd5, 0x04, 0x05, 0x69, 0x51, 0x0a, 0x02, 0x0b, 0x5a, 0xd3, 0x05, 0x03, + 0x2b, 0xed, 0xfc, 0x05, 0x6e, 0x49, 0x05, 0xfb, 0x74, 0xc8, 0xf8, 0x01, 0x9d, 0x2b, 0x05, 0xf7, 0x04, 0x44, 0xd5, + 0xfe, 0xfb, 0xb2, 0x21, 0x00, 0x00, 0x3c, 0xe2, 0x00, 0x00, 0x0a, 0xfd, 0x00, 0x01, 0xb6, 0x1a, 0x07, 0x00, 0x00, + 0x53, 0xd6, 0x00, 0x05, 0xaa, 0x28, 0x00, 0xf8, 0x5d, 0xcf, 0xf8, 0xfe, 0x00, 0xff, 0xfe, 0xfd, 0xcb, 0xfe, 0x0a, + 0xfd, 0xfb, 0x19, 0xf2, 0xff, 0xfe, 0x1b, 0xf4, 0x03, 0x04, 0x26, 0xf1, 0x02, 0x06, 0x1e, 0x00, 0x23, 0x3c, 0x5f, + 0x0b, 0x00, 0x00, 0x05, 0x00, 0x04, 0xf9, 0x00, 0xfe, 0xff, 0x00, 0xfe, 0x02, 0xf9, 0x00, 0xfe, 0x02, 0x00, 0xfd, + 0x01, 0xfd, 0x02, 0x00, 0xfe, 0x00, 0xfe, 0xfd, 0x02, 0x03, 0x9f, 0xb6, 0x00, 0x05, 0x03, 0x02, 0x05, 0x00, 0x06, + 0x00, 0x07, 0x02, 0x00, 0x06, 0x00, 0x03, 0x04, 0x00, 0x05, 0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0xfe, 0x03, 0xff, + 0xfc, 0x02, 0x58, 0x4d, 0x03, 0xfb, 0xf9, 0xfb, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xf7, 0xfd, 0xfb, 0xfb, 0xfb, 0x00, + 0xfa, 0xfe, 0xfb, 0xfe, 0x00, 0xfd, 0x00, 0xff, 0xfe, 0xfe, 0x02, 0x00, 0xfe, 0x04, 0x99, 0xb4, 0xfe, 0x04, 0x03, + 0x05, 0x03, 0x04, 0x03, 0x05, 0x03, 0x03, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, + 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0x6f, 0x42, 0x03, 0xfb, 0xfb, 0xfb, 0xfa, 0xfd, 0xfb, 0xfc, 0xfb, 0xfb, 0xfd, + 0xfb, 0xff, 0xfe, 0x02, 0xfb, 0xfe, 0xfe, 0xff, 0xfe, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04, 0x89, + 0xbc, 0xfe, 0x05, 0x05, 0x03, 0x05, 0x04, 0x03, 0x05, 0x03, 0x02, 0x03, 0x02, 0x01, 0x02, 0x03, 0x02, 0x02, 0x01, + 0x02, 0x02, 0x01, 0xff, 0xfe, 0xfe, 0x02, 0xfe, 0xff, 0x01, 0x7c, 0x3c, 0x05, 0xf9, 0xfd, 0xfb, 0xfb, 0xfd, 0xfc, + 0xfd, 0xfb, 0xfd, 0x00, 0xfe, 0xfd, 0xfe, 0x02, 0xfd, 0x00, 0xfe, 0xfe, 0x02, 0xfe, 0x00, 0x00, 0x04, 0x00, 0x01, + 0x02, 0x00, 0x03, 0x7c, 0xc4, 0xff, 0x05, 0x05, 0x01, 0x05, 0x04, 0x05, 0x03, 0x00, 0x02, 0x03, 0xfe, 0x02, 0x00, + 0x01, 0x04, 0xfc, 0x04, 0x01, 0xff, 0x01, 0xff, 0x01, 0x02, 0xfd, 0xfe, 0x00, 0x00, 0x8d, 0x34, 0x04, 0xfc, 0xfa, + 0xfd, 0xfc, 0xfb, 0x05, 0xfd, 0xfe, 0x00, 0xfd, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xfe, 0x02, 0xfe, 0xfe, 0x04, 0xfc, + 0x02, 0x05, 0xfd, 0x00, 0x00, 0x00, 0x05, 0x70, 0xc9, 0x00, 0x02, 0x03, 0x02, 0xfe, 0x04, 0x03, 0xfd, 0x03, 0x02, + 0xfe, 0x03, 0x02, 0xfe, 0x04, 0xfc, 0xf6, 0x0f, 0x00, 0xff, 0x01, 0x00, 0xfa, 0xe7, 0x10, 0xff, 0x00, 0x15, 0xf6, + 0xfb, 0x05, 0xfd, 0xc6, 0x20, 0x00, 0x01, 0x14, 0xfd, 0xfb, 0x01, 0xfd, 0x11, 0xf9, 0x00, 0x00, 0x9d, 0x33, 0x02, + 0x00, 0x01, 0x1e, 0xee, 0x00, 0x00, 0x0a, 0xfb, 0x02, 0xfc, 0xfd, 0x6d, 0xc8, 0xfb, 0x06, 0x83, 0x3d, 0x05, 0xfe, + 0xf3, 0xec, 0x0a, 0xfd, 0xfe, 0x58, 0xd5, 0xf9, 0x00, 0x04, 0x10, 0xf8, 0x00, 0x03, 0x8d, 0x38, 0x05, 0x01, 0x3c, + 0x1d, 0xe6, 0x03, 0x04, 0x17, 0xf6, 0x00, 0x05, 0xfc, 0xf3, 0x09, 0x04, 0xff, 0xa7, 0x22, 0x09, 0xfc, 0x16, 0xfc, + 0xfc, 0x00, 0x01, 0xf5, 0x05, 0x05, 0xfe, 0x0d, 0x11, 0xf2, 0xff, 0x01, 0x95, 0x33, 0x04, 0xfc, 0xdf, 0x09, 0x00, + 0xfb, 0xfc, 0xc8, 0x9a, 0xf4, 0x02, 0xb1, 0xed, 0x1b, 0xfc, 0xfd, 0xf3, 0x05, 0x00, 0xfe, 0x56, 0xd4, 0xfc, 0x02, + 0x0b, 0x37, 0xe4, 0x01, 0x04, 0xb1, 0x17, 0x0f, 0xfe, 0xfe, 0x33, 0xe9, 0x00, 0x04, 0x24, 0x19, 0xf2, 0x02, 0xf9, + 0xe4, 0x13, 0x01, 0x00, 0x3c, 0xe7, 0xfe, 0x04, 0xfe, 0x9f, 0x2f, 0x00, 0x00, 0xee, 0xff, 0x05, 0xfb, 0xea, 0xf1, + 0x0a, 0xfd, 0x00, 0xfe, 0xfb, 0xff, 0x00, 0x0a, 0x52, 0xd3, 0xfd, 0x00, 0xbd, 0x12, 0x06, 0xff, 0xdd, 0x02, 0x06, + 0x02, 0xfe, 0xfd, 0x03, 0x02, 0x03, 0x1c, 0x51, 0xd8, 0xff, 0x05, 0xd5, 0x15, 0x09, 0x01, 0x02, 0x0d, 0xfb, 0x03, + 0x04, 0xe7, 0x10, 0x04, 0x03, 0x29, 0x11, 0xf1, 0x05, 0x05, 0x8e, 0x3a, 0x03, 0x00, 0xfd, 0xf6, 0x06, 0xfc, 0x03, + 0x26, 0xe9, 0x01, 0xfd, 0xf6, 0x03, 0xff, 0xfe, 0x02, 0x03, 0xfe, 0x02, 0x00, 0x21, 0x29, 0xe6, 0x00, 0xf6, 0xd2, + 0x1a, 0x00, 0x00, 0x19, 0xf9, 0xfd, 0x05, 0x00, 0xb9, 0x28, 0x00, 0x01, 0x02, 0x03, 0xfd, 0x02, 0x00, 0xf7, 0x0a, + 0xfd, 0x00, 0x6a, 0xd0, 0xfb, 0x01, 0x04, 0x0a, 0xf9, 0x02, 0x00, 0x7f, 0x17, 0x16, 0xf9, 0xf6, 0x90, 0xc7, 0xf9, + 0x05, 0x41, 0x5d, 0x07, 0xf9, 0x05, 0x14, 0xef, 0xfd, 0xfd, 0xf4, 0x03, 0x02, 0x00, 0x70, 0xea, 0xf0, 0x02, 0x01, + 0x02, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x01, 0xff, 0x01, 0x00, 0x05, 0xff, 0x00, 0x03, 0xfe, 0x05, 0xff, 0x03, 0xfe, + 0x03, 0xff, 0xfe, 0xfd, 0x00, 0xfe, 0xdc, 0x85, 0x40, 0xff, 0xfc, 0xfd, 0xfd, 0xfe, 0xfd, 0xf9, 0x00, 0xfd, 0xfe, + 0xff, 0xf9, 0x00, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xfe, 0xfb, 0x03, 0x00, 0xff, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x05, 0xff, 0x0d, 0xa0, 0xb2, 0x03, 0x00, 0x05, 0x03, 0x03, 0x02, 0x07, 0x01, 0x04, 0x03, 0x03, + 0x03, 0x04, 0x03, 0x02, 0x03, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfd, 0x00, 0xfe, 0x00, + 0x00, 0xfe, 0x00, 0xff, 0xfd, 0x95, 0x07, 0x13, 0xfb, 0xfd, 0xfb, 0xfb, 0xff, 0xfc, 0xfd, 0xfb, 0xfe, 0xff, 0xfc, + 0xfd, 0xff, 0xfe, 0x02, 0xfb, 0x05, 0xfb, 0x00, 0x00, 0xfe, 0x03, 0xfd, 0x00, 0x02, 0x00, 0x00, 0x03, 0xfe, 0x02, + 0x03, 0xff, 0x03, 0xfe, 0xfd, 0xae, 0xaa, 0xff, 0x03, 0x05, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, + 0xff, 0x03, 0x02, 0x00, 0x03, 0xfe, 0x03, 0x02, 0xfd, 0x03, 0x00, 0xfd, 0x03, 0x00, 0xfb, 0x02, 0xfd, 0xfe, 0x00, + 0xfe, 0xff, 0xfe, 0xf9, 0xe5, 0xa9, 0x2c, 0xfe, 0xfd, 0xfd, 0xfe, 0xfd, 0xfd, 0xfe, 0xfd, 0xfe, 0x00, 0xfd, 0x00, + 0xfe, 0xfd, 0x00, 0x00, 0xfc, 0x02, 0xfe, 0xff, 0x01, 0x02, 0xfe, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x02, 0x00, 0x79, 0xd4, 0xf8, 0x03, 0x05, 0x03, 0x03, 0x02, 0x03, 0x02, 0x00, 0x02, 0x03, 0x01, 0x00, + 0x02, 0x02, 0xfe, 0x03, 0x02, 0xfe, 0x02, 0x02, 0x00, 0xfc, 0x02, 0x00, 0xfd, 0x01, 0x00, 0xfd, 0x02, 0xfe, 0x00, + 0xfe, 0xff, 0xfe, 0xa9, 0x0a, 0x0f, 0xfd, 0xfb, 0x00, 0xfc, 0xfd, 0xfe, 0x00, 0xff, 0xfd, 0x01, 0xfd, 0xfe, 0x00, + 0xff, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff, 0x00, 0x03, 0xfe, 0xff, 0x05, 0xfe, 0x00, 0x00, 0x02, 0x00, + 0xfe, 0x00, 0xfd, 0x4b, 0xc7, 0x3b, 0xe7, 0x02, 0xd8, 0x2d, 0xd3, 0x05, 0x26, 0xf0, 0x1d, 0xff, 0xda, 0x1c, 0xc0, + 0x53, 0x1e, 0xa9, 0x52, 0xf0, 0xae, 0x69, 0xe0, 0x09, 0xbe, 0x24, 0x17, 0xf5, 0xe4, 0x20, 0x07, 0xb5, 0x4d, 0xf9, + 0xe1, 0x4f, 0x9c, 0x15, 0x34, 0xdb, 0x21, 0xcb, 0x30, 0xbc, 0x1b, 0x55, 0xc3, 0x05, 0xd9, 0x48, 0xcd, 0x05, 0xd5, + 0x76, 0xba, 0xfd, 0xfb, 0xd7, 0x31, 0x0a, 0xf4, 0x1f, 0xbf, 0x2f, 0xc4, 0x73, 0xb1, 0x34, 0xd2, 0x26, 0xd1, 0xf7, + 0x00, 0x24, 0xed, 0x05, 0x01, 0xc9, 0x44, 0x09, 0xef, 0x14, 0xb1, 0x52, 0xd2, 0xf6, 0x21, 0xd9, 0x15, 0x05, 0xf3, + 0xf6, 0xf8, 0x55, 0xdf, 0xc5, 0x3a, 0xda, 0x02, 0x4d, 0x94, 0x31, 0x06, 0xf2, 0xd7, 0x4d, 0xee, 0xe2, 0x07, 0x05, + 0xe7, 0x1c, 0x22, 0xe8, 0xbc, 0x6e, 0xdf, 0xff, 0xfd, 0xda, 0xfe, 0x42, 0xd0, 0x05, 0xd4, 0x55, 0x91, 0x5d, 0x14, + 0xca, 0x13, 0xcc, 0x0d, 0x15, 0x04, 0x18, 0xba, 0x57, 0xcd, 0x0a, 0xd2, 0x41, 0x0a, 0xd2, 0x19, 0xf3, 0xec, 0x10, + 0x0f, 0x24, 0xc5, 0xfd, 0xeb, 0x2e, 0x10, 0xf1, 0xfd, 0x0d, 0xfe, 0xbf, 0x5a, 0xcf, 0xef, 0x17, 0x1e, 0xd7, 0x15, + 0xe4, 0x3f, 0xd5, 0xf4, 0x14, 0x0a, 0xe4, 0xe6, 0x21, 0xf9, 0x0f, 0xf8, 0xf6, 0x27, 0xcf, 0x39, 0xde, 0xd7, 0x3e, + 0xf8, 0xfe, 0xf3, 0x30, 0xc2, 0xf1, 0x3e, 0xc4, 0x18, 0xfd, 0xf9, 0x34, 0xcc, 0x14, 0xfd, 0x10, 0xcd, 0x17, 0x1c, + 0xeb, 0x1a, 0xdc, 0xf8, 0x27, 0xee, 0xe4, 0x0c, 0x31, 0xae, 0x49, 0xd8, 0x2d, 0xe5, 0xfe, 0x0a, 0xe6, 0x13, 0xf8, + 0x02, 0x1f, 0xd0, 0x04, 0x15, 0x02, 0xea, 0xf7, 0x23, 0xf5, 0x0b, 0x0a, 0xc9, 0x2f, 0x03, 0x07, 0xf0, 0xd0, 0x55, + 0xc7, 0x00, 0xf0, 0x10, 0x34, 0xee, 0xc9, 0x2a, 0x0f, 0xe1, 0xfd, 0xee, 0x44, 0xde, 0xe6, 0x1f, 0x0d, 0xec, 0xee, + 0x0f, 0xf3, 0x00, 0x18, 0xf3, 0x05, 0xf8, 0x33, 0xa8, 0x1b, 0xff, 0x0d, 0x06, 0xf6, 0x1b, 0xd2, 0x17, 0x18, 0xd3, + 0x2a, 0xcf, 0x3b, 0xf8, 0xe9, 0x17, 0xe4, 0xfe, 0x33, 0xb3, 0x50, 0xb7, 0x3a, 0xe1, 0xeb, 0x26, 0xdd, 0x19, 0x1c, + 0xd8, 0xff, 0x12, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x03, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x7f, 0x01, 0xff, 0x00, 0x01, 0x00, 0x80, 0x7f, 0x01, 0xff, 0x01, 0xff, 0x00, 0x01, 0xff, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0xff, 0x01, 0x00, + 0xff, 0x01, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x01, 0x00, + 0x80, 0x7f, 0x01, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, + 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf5, 0x00, 0xff, 0xfe, + 0xfa, 0x00, 0xfd, 0xf2, 0xf7, 0xff, 0xfc, 0xfd, 0x34, 0x00, 0x0c, 0x0b, 0x08, 0x01, 0x05, 0x04, 0x03, 0x01, 0x00, + 0x02, 0x01, 0x04, 0x00, 0x01, 0x06, 0xc2, 0x00, 0xff, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfa, 0xfd, + 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfe, 0xff, 0x00, 0x00, 0xfe, 0x20, 0x03, 0x01, 0x05, 0x0e, 0x13, 0x0a, 0x01, + 0x05, 0x06, 0x05, 0x00, 0x04, 0x05, 0x05, 0x00, 0x03, 0x03, 0x05, 0x01, 0x03, 0x03, 0x04, 0x01, 0x02, 0x00, 0x0e, + 0x01, 0x00, 0x03, 0x81, 0xfe, 0xff, 0x00, 0xfd, 0xfe, 0x00, 0xff, 0xfe, 0xff, 0x00, 0xfd, 0xfb, 0xfd, 0x00, 0xfe, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x29, 0x03, 0x05, 0x00, 0x03, 0x05, 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x02, 0x03, 0x05, 0x00, 0x05, + 0x05, 0x03, 0x04, 0x00, 0x03, 0x04, 0x03, 0x00, 0x01, 0x02, 0x03, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xff, 0xfe, + 0xfd, 0xfe, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0xfd, 0xff, 0xff, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x07, 0x01, 0x02, + 0x01, 0x03, 0x01, 0x01, 0x03, 0x02, 0x04, 0x00, 0x02, 0x01, 0x04, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x00, 0x03, 0x02, 0x03, 0x00, 0x01, 0x05, 0x03, 0x03, 0x01, 0x04, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0xff, 0xfc, 0xfb, 0x00, 0xff, 0xff, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x02, 0x04, 0x07, + 0x01, 0x05, 0x08, 0x04, 0x01, 0x06, 0x06, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x00, 0x00, 0x01, 0x03, 0x01, 0x01, + 0x03, 0x01, 0x01, 0x01, 0x03, 0x02, 0x01, 0x02, 0x01, 0x07, 0x01, 0x00, 0x05, 0x06, 0x03, 0x01, 0x02, 0x04, 0x01, + 0x00, 0x02, 0x06, 0x06, 0x00, 0x02, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfd, 0x00, 0xfe, 0xfd, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x13, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x01, 0x03, 0x05, 0x05, 0x01, 0x05, 0x05, 0x03, 0x05, 0x00, 0x03, 0x01, 0x02, + 0x01, 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, + 0x03, 0x02, 0x01, 0x00, 0x04, 0x01, 0x01, 0x04, 0x01, 0x00, 0x00, 0x04, 0x03, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfe, 0xfd, 0xfd, 0xff, 0x00, 0xfb, + 0xfd, 0xff, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3d, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x26, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, + 0x15, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x91, 0x95, 0x01, 0x81, 0x2a, 0xe5, 0x11, 0xfe, 0x89, 0x58, + 0x5a, 0x14, 0x01, 0xed, 0x26, 0x3f, 0x23, 0xb6, 0x30, 0xa0, 0x29, 0xc6, 0xc3, 0xbc, 0x2c, 0x1e, 0x07, 0x6e, 0x59, + 0xe6, 0xf8, 0xed, 0x57, 0x3a, 0xa1, 0xae, 0xbf, 0xce, 0x30, 0x02, 0xe3, 0xe8, 0x68, 0x16, 0xda, 0xc5, 0x06, 0x64, + 0xe0, 0xe1, 0xa9, 0x30, 0x28, 0x6b, 0xd1, 0xed, 0x2d, 0x22, 0x7e, 0x7c, 0x81, 0x03, 0xfe, 0xdb, 0x42, 0x12, 0x87, + 0x4a, 0x38, 0x7a, 0x1a, 0x92, 0xab, 0x74, 0x55, 0x52, 0x03, 0x2e, 0xab, 0x16, 0x49, 0x0c, 0xa4, 0x0f, 0x94, 0x84, + 0xba, 0x3e, 0x5e, 0x09, 0x45, 0xd7, 0x03, 0x22, 0x2f, 0xb6, 0x41, 0x30, 0xd8, 0xb5, 0xef, 0x07, 0xda, 0xb2, 0xec, + 0xc9, 0x32, 0x0a, 0x5c, 0x49, 0x4b, 0x70, 0x38, 0x40, 0xa0, 0xdc, 0x56, 0xa9, 0x62, 0x68, 0xe0, 0x99, 0xca, 0xf6, + 0x58, 0xda, 0x9b, 0x52, 0x42, 0x97, 0x6a, 0xc6, 0x67, 0x84, 0x2f, 0xd3, 0xe3, 0xa2, 0xc4, 0xec, 0xf7, 0x1d, 0xd3, + 0x01, 0xb2, 0x77, 0xcb, 0xa0, 0x91, 0x60, 0x5c, 0x98, 0x07, 0x89, 0x23, 0xc4, 0x2a, 0xaa, 0x04, 0xf6, 0x65, 0x37, + 0xc6, 0xbf, 0x55, 0xf3, 0x81, 0xd8, 0xfb, 0xb1, 0x77, 0x1b, 0x17, 0xa7, 0xd8, 0xc8, 0xf0, 0x98, 0x04, 0xdc, 0x8d, + 0x22, 0xee, 0x67, 0x56, 0x7c, 0x1d, 0x99, 0x52, 0x08, 0xd8, 0x5b, 0xf6, 0xf4, 0x1d, 0x58, 0x9e, 0x44, 0xef, 0x13, + 0xcd, 0x90, 0x75, 0x27, 0x2a, 0xd2, 0xa3, 0x33, 0x58, 0x82, 0xd7, 0x79, 0xc9, 0x57, 0x0b, 0xe0, 0x7f, 0x0b, 0x30, + 0x3c, 0xd8, 0x59, 0x38, 0xa7, 0x77, 0x9d, 0x5b, 0xb1, 0x5a, 0x51, 0x45, 0x47, 0x28, 0xce, 0x8a, 0x11, 0xd1, 0x7d, + 0x2c, 0x22, 0x80, 0xfa, 0x84, 0xd6, 0xf3, 0x54, 0x58, 0x7c, 0x68, 0xb8, 0x8a, 0xe6, 0xf8, 0xee, 0xf2, 0x6f, 0x98, + 0xf3, 0x13, 0x64, 0xca, 0xf0, 0xfe, 0xa6, 0x05, 0xe7, 0x3c, 0x48, 0xe1, 0x6e, 0x1b, 0xe4, 0x2f, 0xbd, 0xf8, 0xbe, + 0xe7, 0x65, 0x27, 0x28, 0x23, 0xfa, 0x00, 0x42, 0x18, 0x0c, 0x8a, 0xba, 0x35, 0xac, 0x89, 0x73, 0x64, 0xe0, 0x45, + 0xd6, 0x8e, 0x4b, 0xbc, 0xac, 0x59, 0x64, 0xc8, 0x36, 0x5f, 0x72, 0xd1, 0x6e, 0xb4, 0xbd, 0x7f, 0x3f, 0xf0, 0x39, + 0x1f, 0x65, 0xd3, 0xe6, 0x2f, 0xfe, 0x5f, 0x66, 0xb9, 0x50, 0xd0, 0xcc, 0xf9, 0xe6, 0x1f, 0x58, 0xe9, 0x91, 0x69, + 0x0d, 0x3a, 0x47, 0x34, 0xb4, 0x5f, 0x94, 0x93, 0x86, 0x14, 0x89, 0x47, 0xc6, 0x21, 0xdb, 0xf0, 0xa1, 0xc0, 0x22, + 0x58, 0xb0, 0x46, 0xe3, 0xe1, 0x58, 0xa5, 0x5a, 0x42, 0x59, 0x5a, 0xb6, 0x73, 0xff, 0x2d, 0xb6, 0x07, 0x0c, 0x9d, + 0x4c, 0xf5, 0xd8, 0x47, 0x42, 0xc8, 0xea, 0xf0, 0x9b, 0x6b, 0x50, 0xcc, 0x7e, 0x89, 0x14, 0x82, 0x81, 0x9d, 0x11, + 0x86, 0x22, 0xb6, 0x8d, 0x4e, 0x4b, 0x07, 0xcb, 0x05, 0x91, 0x5f, 0xf4, 0x3c, 0x20, 0x77, 0xb9, 0x30, 0x14, 0x47, + 0xda, 0x26, 0x0e, 0x6a, 0xf6, 0x96, 0xd9, 0x94, 0xfb, 0x7b, 0xed, 0x37, 0x77, 0x88, 0xa5, 0x61, 0x22, 0xb8, 0xf2, + 0xe9, 0xe8, 0xdb, 0x58, 0xf3, 0xd5, 0x99, 0x10, 0xe4, 0x23, 0x8f, 0x1c, 0xc6, 0xbb, 0x0d, 0x0d, 0x49, 0x86, 0x0b, + 0x69, 0x49, 0xcd, 0xe0, 0x5c, 0x16, 0xfd, 0x43, 0xb4, 0x61, 0x36, 0x39, 0xbb, 0x07, 0xc5, 0x79, 0xf8, 0xa9, 0x0a, + 0xc2, 0x88, 0x3a, 0xfb, 0xdb, 0xe2, 0x7a, 0xa4, 0x9f, 0xdf, 0x8f, 0xe7, 0xce, 0xd1, 0xa7, 0xd7, 0x1c, 0x73, 0xce, + 0xff, 0x08, 0x91, 0x01, 0xd5, 0x26, 0x25, 0x85, 0xbb, 0x56, 0xd0, 0x9a, 0xdc, 0x75, 0x64, 0xa6, 0x1a, 0x37, 0x61, + 0xc7, 0x99, 0x85, 0x3e, 0xf7, 0xe8, 0x2e, 0x2e, 0xdb, 0x5e, 0x43, 0x46, 0x26, 0xcd, 0xd1, 0xee, 0xbd, 0xfd, 0x7e, + 0x23, 0xb1, 0x1a, 0x98, 0xb0, 0x0c, 0x83, 0x21, 0xf0, 0x86, 0x48, 0x77, 0x06, 0x3c, 0x90, 0x1c, 0x54, 0x69, 0x4f, + 0x2c, 0xff, 0x49, 0x90, 0x1a, 0x5c, 0x12, 0xa8, 0x4a, 0xef, 0x3d, 0x9d, 0xf6, 0x15, 0x0e, 0x18, 0x1b, 0xd5, 0x75, + 0x2a, 0xe4, 0xea, 0x67, 0x3b, 0x22, 0xa8, 0x9e, 0x70, 0x6c, 0xb6, 0xfe, 0xd1, 0x75, 0x42, 0x7b, 0x92, 0x1a, 0xa6, + 0xb6, 0xbf, 0xd0, 0x26, 0x60, 0x90, 0xee, 0xcb, 0x4e, 0xe3, 0x65, 0xef, 0x7f, 0xeb, 0x8b, 0x7d, 0x04, 0x9e, 0x67, + 0x95, 0xe2, 0x0c, 0x31, 0x6e, 0x00, 0x0e, 0x6e, 0x5a, 0x30, 0x76, 0x68, 0x8a, 0x68, 0x31, 0x71, 0x94, 0x2f, 0xa7, + 0x79, 0x85, 0x4f, 0x9a, 0xae, 0x1b, 0xfe, 0xd0, 0x94, 0x48, 0x4d, 0x04, 0x2f, 0x84, 0x2a, 0x2c, 0xd2, 0xf7, 0xe7, + 0x9d, 0x22, 0x1e, 0x5d, 0x39, 0xdb, 0xdb, 0xae, 0x0f, 0xe5, 0xb0, 0xe4, 0x9f, 0x57, 0xf5, 0x26, 0x42, 0xdf, 0xe9, + 0xfc, 0xd2, 0x2f, 0x53, 0x5f, 0xf7, 0x0c, 0xa1, 0xc9, 0x86, 0x6c, 0x36, 0x5e, 0x00, 0x55, 0xd5, 0x19, 0xd3, 0xf5, + 0xe3, 0x3d, 0x56, 0x9b, 0x58, 0xec, 0x23, 0xfe, 0x3b, 0x12, 0xdc, 0x8f, 0x57, 0xae, 0xd9, 0x39, 0x21, 0x84, 0xf0, + 0x41, 0x89, 0x42, 0xbb, 0xc9, 0x88, 0x3a, 0xac, 0x74, 0x36, 0xba, 0x20, 0xf1, 0x50, 0xfa, 0xf8, 0xae, 0xe2, 0xe2, + 0xd2, 0x8e, 0xe8, 0x83, 0x53, 0x07, 0xd3, 0x7c, 0xc1, 0x3f, 0x9c, 0x3b, 0x53, 0xc5, 0x45, 0x48, 0x67, 0x5f, 0xb2, + 0x89, 0x03, 0xa2, 0x67, 0xba, 0xf4, 0xb4, 0x4c, 0xf8, 0xd5, 0xea, 0x0f, 0x90, 0x3a, 0xd9, 0xfd, 0x1c, 0x7e, 0x40, + 0x3e, 0xfd, 0x52, 0x82, 0x1e, 0x32, 0x7c, 0x39, 0x50, 0xbd, 0x0c, 0x5d, 0xed, 0x82, 0x59, 0xae, 0xfe, 0xcc, 0x13, + 0xd0, 0x6a, 0x7e, 0xbb, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xed, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xeb, 0x0d, 0x00, 0x00, 0x20, 0x00, 0x02, 0x80, 0xfc, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xfc, 0x13, 0xe3, 0xe0, + 0x06, 0x48, 0x22, 0x6a, 0x10, 0x9e, 0x56, 0x8a, 0x85, 0xbb, 0x1b, 0xd5, 0x25, 0x99, 0xd0, 0x40, 0x8c, 0x46, 0xec, + 0x14, 0x84, 0x92, 0x5a, 0x13, 0xd5, 0x6c, 0xfe, 0x34, 0x7a, 0x12, 0xde, 0x80, 0x37, 0xcd, 0xee, 0x1e, 0x30, 0xd7, + 0xbb, 0x77, 0x89, 0x0a, 0xe5, 0x8f, 0x3d, 0x15, 0x98, 0xcc, 0x6a, 0x41, 0x79, 0x7a, 0xc6, 0x3c, 0x6a, 0x80, 0x28, + 0x95, 0xb9, 0xe0, 0x10, 0x9a, 0x14, 0xbc, 0xee, 0x6c, 0x44, 0x92, 0x4a, 0x24, 0x16, 0xf2, 0x2f, 0xdb, 0x30, 0xb2, + 0x9e, 0x21, 0x2d, 0xb2, 0x12, 0x8e, 0xc2, 0x44, 0xbe, 0x24, 0xf6, 0x82, 0x77, 0xfd, 0x17, 0x25, 0xd6, 0xc0, 0x84, + 0x97, 0xe0, 0x9f, 0x5e, 0x2e, 0x7c, 0x30, 0x80, 0x08, 0xa1, 0x4f, 0x0e, 0xae, 0x4a, 0x28, 0x85, 0x6d, 0x9e, 0x60, + 0xc2, 0x26, 0xfa, 0x2c, 0xba, 0xf6, 0x4a, 0xca, 0x18, 0xbc, 0x53, 0x1d, 0x84, 0x56, 0x26, 0x82, 0x64, 0xc2, 0x3f, + 0xb3, 0xee, 0x54, 0xbc, 0x3c, 0xb2, 0x55, 0x11, 0xaa, 0x20, 0xeb, 0x09, 0x02, 0x26, 0x00, 0x9c, 0x9a, 0xff, 0x6b, + 0x6a, 0xc1, 0x49, 0xd0, 0x26, 0xe0, 0x10, 0x06, 0xe1, 0xf0, 0x3d, 0xd4, 0x2e, 0x1a, 0x7e, 0x10, 0x3c, 0x22, 0xb6, + 0xcf, 0x9f, 0xb0, 0xe4, 0x02, 0x54, 0xb0, 0x3a, 0x9a, 0x66, 0xd0, 0x31, 0xf7, 0xea, 0x34, 0x9a, 0x5c, 0xce, 0x12, + 0x28, 0x86, 0x92, 0xac, 0xbe, 0x90, 0x8c, 0xee, 0x62, 0xe9, 0xe3, 0x09, 0x45, 0x8a, 0x84, 0x9a, 0x22, 0xd8, 0x2a, + 0xd3, 0x61, 0x82, 0x78, 0x90, 0x1c, 0x68, 0x73, 0x5d, 0xce, 0x54, 0x90, 0x36, 0x0a, 0xf2, 0xfe, 0x30, 0x86, 0x96, + 0x5a, 0x8a, 0xa4, 0x2e, 0x0e, 0x00, 0x0a, 0xb6, 0x66, 0xae, 0x4c, 0x8c, 0x94, 0x76, 0x22, 0x66, 0x6c, 0x64, 0xc0, + 0x26, 0x20, 0xbc, 0x3e, 0xd6, 0x22, 0xab, 0x31, 0x3e, 0xc6, 0xee, 0xfb, 0x51, 0xad, 0x25, 0xea, 0x24, 0xee, 0x08, + 0x20, 0xb2, 0x46, 0xd1, 0x25, 0xe0, 0x1a, 0x00, 0x2c, 0xa1, 0x3b, 0xea, 0xd8, 0x56, 0xc2, 0x0a, 0x34, 0xc8, 0xf8, + 0x2f, 0xd3, 0x00, 0x50, 0x79, 0x5d, 0xf2, 0x0d, 0xad, 0x84, 0x86, 0x72, 0x98, 0x3a, 0xf6, 0xd2, 0x68, 0x8e, 0x62, + 0x8a, 0x54, 0x2c, 0x7e, 0x4a, 0x1c, 0xd0, 0x1f, 0xdb, 0x0d, 0x15, 0x06, 0xfa, 0xe4, 0x42, 0x9a, 0x43, 0x01, 0x02, + 0xee, 0xac, 0xa0, 0xab, 0x09, 0x06, 0x04, 0xd6, 0x40, 0x02, 0x81, 0x8c, 0xb1, 0x40, 0xca, 0x48, 0xba, 0x16, 0x08, + 0x22, 0xb4, 0x2e, 0xec, 0x08, 0x04, 0xe8, 0x44, 0xc0, 0x1c, 0x19, 0xd5, 0xee, 0x1e, 0x04, 0x0e, 0x00, 0xc6, 0x1c, + 0x1a, 0x16, 0xb6, 0x46, 0xc2, 0x38, 0xe2, 0x08, 0xe0, 0x55, 0xa7, 0x2f, 0xc7, 0x0c, 0x22, 0x46, 0x6e, 0x1e, 0x64, + 0xa9, 0x15, 0xfa, 0x00, 0x18, 0x00, 0xf8, 0xf5, 0x1f, 0xc0, 0x26, 0x2e, 0xb4, 0x34, 0xf2, 0xec, 0x1a, 0xef, 0xe6, + 0x33, 0xe6, 0x1a, 0xd0, 0x5c, 0x72, 0x68, 0xd6, 0xf8, 0x32, 0xf0, 0xfa, 0x26, 0xca, 0x12, 0xf2, 0xe6, 0x63, 0x99, + 0x04, 0x3b, 0x13, 0x9c, 0x3a, 0xe6, 0x1b, 0xfd, 0x1a, 0xba, 0x46, 0xf0, 0x08, 0xd8, 0x14, 0x0e, 0xf6, 0x0a, 0xf6, + 0xe2, 0x45, 0xd9, 0xe0, 0x44, 0xc4, 0x14, 0xfe, 0xf4, 0x2a, 0xd8, 0x1a, 0xe0, 0x1a, 0x04, 0x10, 0xc4, 0x44, 0xd4, + 0x06, 0xe0, 0x4c, 0xba, 0x1e, 0xec, 0x3e, 0xb8, 0x1e, 0x06, 0xec, 0x06, 0xfa, 0x08, 0x0c, 0xec, 0x14, 0xe8, 0x28, + 0xd2, 0x1c, 0xe0, 0x2e, 0x00, 0xde, 0x0e, 0x02, 0xef, 0x17, 0x04, 0xe0, 0x30, 0xcc, 0x24, 0xd8, 0x56, 0xa2, 0x11, + 0x39, 0xb9, 0x33, 0xfa, 0xe0, 0x2c, 0xd6, 0x08, 0x26, 0xe4, 0xee, 0x04, 0x28, 0xd4, 0x18, 0x08, 0xd8, 0x16, 0x06, + 0x0c, 0xe8, 0x0b, 0x25, 0xba, 0x3a, 0xc5, 0x2b, 0xde, 0x2e, 0xc8, 0x3c, 0xcc, 0x36, 0xdf, 0x19, 0xdc, 0x14, 0xe8, + 0x1e, 0xfc, 0xe3, 0x2d, 0xdc, 0x01, 0x1f, 0xe8, 0x0a, 0xee, 0x09, 0x13, 0xe6, 0x0a, 0x0a, 0x1a, 0xc0, 0x2c, 0xf4, + 0xf2, 0xfe, 0x14, 0xf8, 0xfe, 0x18, 0xd4, 0x2d, 0xdf, 0x02, 0x12, 0x06, 0xee, 0xe3, 0x45, 0xca, 0x00, 0x24, 0xf4, + 0xf6, 0x0a, 0xec, 0x12, 0x00, 0x06, 0xee, 0x00, 0x06, 0x0a, 0xea, 0x2a, 0xd6, 0x14, 0xf8, 0xfe, 0x11, 0xee, 0x05, + 0x1c, 0xd6, 0x24, 0xbe, 0x34, 0x00, 0x01, 0xf3, 0x0a, 0xde, 0x30, 0xd6, 0x34, 0xd8, 0x06, 0x04, 0x23, 0xb5, 0x28, + 0xfc, 0x0e, 0xfa, 0xf2, 0x14, 0xea, 0x2a, 0xd0, 0x1a, 0xf8, 0xfe, 0x10, 0xe6, 0x14, 0xee, 0x14, 0xf3, 0x05, 0x11, + 0xdd, 0x12, 0x02, 0xf2, 0x0a, 0xf8, 0x10, 0xfc, 0xfc, 0x0e, 0xe5, 0x31, 0xb4, 0x2e, 0x12, 0xd6, 0x16, 0x02, 0x04, + 0xe0, 0x1a, 0xfe, 0x0c, 0xe2, 0x0a, 0x04, 0x26, 0xc2, 0x24, 0xf9, 0xf1, 0x0f, 0x0f, 0xd6, 0x18, 0x0e, 0xef, 0xfb, + 0x06, 0x04, 0x0c, 0xd6, 0x24, 0xea, 0x2c, 0xd0, 0x12, 0xfe, 0x0a, 0xef, 0x07, 0x00, 0xee, 0x22, 0xdf, 0x2f, 0xbe, + 0x34, 0xe8, 0x18, 0xe6, 0x14, 0xfa, 0xfa, 0x0e, 0xf0, 0x0a, 0x04, 0xf6, 0xf2, 0x0a, 0x0e, 0x0c, 0xe4, 0x14, 0xe2, + 0x20, 0xee, 0x11, 0xf1, 0xf6, 0x16, 0xf6, 0x00, 0x0c, 0xf8, 0xf2, 0x16, 0xdc, 0x26, 0xea, 0x0a, 0xf6, 0x10, 0xf5, + 0x05, 0x20, 0xbd, 0x21, 0x16, 0xdc, 0x02, 0x18, 0xe6, 0x38, 0xaa, 0x35, 0x05, 0xee, 0x02, 0x0c, 0xec, 0x07, 0x03, + 0x08, 0xe2, 0x24, 0xf4, 0xec, 0x17, 0xfb, 0xfb, 0x0d, 0xea, 0x20, 0xdb, 0x29, 0xe0, 0xf6, 0x22, 0xfc, 0xe4, 0x0c, + 0x14, 0xed, 0x0b, 0xf8, 0x02, 0xf4, 0x16, 0x0a, 0xc4, 0x36, 0x06, 0xd5, 0x1f, 0xef, 0x0f, 0xfe, 0xfe, 0xf8, 0xfc, + 0x14, 0xf8, 0xf4, 0x18, 0xe4, 0x1c, 0xe3, 0x1d, 0xf0, 0xfd, 0x05, 0xf0, 0x13, 0xfb, 0x0a, 0xec, 0x17, 0xe3, 0x1a, + 0xfc, 0x02, 0xf0, 0x12, 0xf4, 0xfe, 0x0a, 0x06, 0xfe, 0xf4, 0x01, 0x01, 0x06, 0x07, 0xe8, 0x29, 0xca, 0x28, 0xec, + 0x14, 0xe8, 0x0d, 0x02, 0xfb, 0xf6, 0x08, 0x02, 0x06, 0xfa, 0x04, 0x02, 0xf8, 0x10, 0xe4, 0x12, 0xfa, 0x02, 0x08, + 0xf2, 0x12, 0xf6, 0xfc, 0xfc, 0x0a, 0x02, 0xf8, 0x06, 0xf6, 0x14, 0xe0, 0x27, 0xd7, 0x1a, 0xf4, 0x06, 0x06, 0xf8, + 0xfe, 0x02, 0x08, 0xf4, 0x02, 0x08, 0x02, 0xf5, 0x13, 0xe5, 0x0b, 0x0e, 0xf4, 0xfa, 0xfb, 0x0b, 0x08, 0xec, 0x1a, + 0xea, 0x10, 0xfa, 0xfa, 0x06, 0xfe, 0x00, 0x00, 0x08, 0x06, 0xe8, 0x0e, 0xf0, 0x19, 0xe9, 0x0e, 0x10, 0xd6, 0x1b, + 0xff, 0x0a, 0xe8, 0x14, 0xf0, 0x04, 0x04, 0xfa, 0x12, 0xe0, 0x25, 0xe1, 0x14, 0xf6, 0x10, 0xe8, 0x16, 0xf6, 0xfc, + 0xfd, 0x0c, 0xf7, 0x04, 0x06, 0xf2, 0x10, 0xf1, 0x03, 0x06, 0x00, 0xfe, 0x08, 0xfa, 0xef, 0x11, 0x08, 0xf2, 0xfc, + 0x1a, 0xd4, 0x22, 0xf4, 0x06, 0xfa, 0x07, 0x01, 0x00, 0x00, 0x41, 0x20, 0x73, 0x70, 0x65, 0x63, 0x74, 0x65, 0x72, + 0x20, 0x6e, 0x6f, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x02, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x02, 0x00, 0x03, 0x35, 0x5a, + 0xfb, 0x7c, 0xf2, 0xfb, 0xff, 0x01, 0x05, 0x00, 0xfa, 0xfb, 0xff, 0xfe, 0x00, 0x08, 0x03, 0xfd, 0xfd, 0x00, 0x07, + 0x01, 0x00, 0x00, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e, 0x2e, + 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x02, + 0x03, 0x03, 0x06, 0x03, 0x02, 0x00, 0x00, 0x03, 0x0a, 0x25, 0x5e, 0x00, 0x00, 0x02, 0x00, 0x05, 0xd6, 0x88, 0x00, + 0x00, 0xff, 0xfc, 0xff, 0x05, 0x01, 0x00, 0xff, 0xfe, 0xfe, 0x00, 0x07, 0x01, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x32, 0x30, 0x32, 0x34, 0x00, + 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xfb, 0x43, + 0x5d, 0x02, 0x05, 0x00, 0xfe, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x07, 0xfe, 0xfd, 0xc5, 0xa3, 0xfe, 0x00, 0xfd, 0x00, + 0x00, 0xfd, 0xfb, 0xfd, 0x07, 0x01, 0x00, 0x00, 0x44, 0x72, 0x6f, 0x7a, 0x65, 0x72, 0x69, 0x78, 0x40, 0x67, 0x6d, + 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x01, 0x80, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa9, 0x00, 0xfe, 0x05, 0x08, 0x03, 0x0b, 0x84, 0x0b, 0x09, 0x01, 0x02, 0x03, 0x03, 0x00, 0xff, + 0xfe, 0xfe, 0xfc, 0xfb, 0xfd, 0xff, 0xfc, 0x00, 0x00, 0x89, 0xfa, 0xf5, 0x0f, 0xf8, 0xf6, 0x00}; +} \ No newline at end of file diff --git a/src/resources.cpp b/src/resources.cpp index 09f0ea5..d4bfa54 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -1,17 +1,20 @@ #include "resources.h" -void resources_init(Resources* self) -{ - texture_from_encoded_data_init(&self->atlas, TEXTURE_ATLAS_SIZE, (u8*)TEXTURE_ATLAS, TEXTURE_ATLAS_LENGTH); - - for (s32 i = 0; i < SHADER_COUNT; i++) - shader_init(&self->shaders[i], SHADER_DATA[i].vertex, SHADER_DATA[i].fragment); -} +#include -void resources_free(Resources* self) -{ - for (auto& shader : self->shaders) - shader_free(&shader); +using namespace anm2ed::resource; - texture_free(&self->atlas); +namespace anm2ed +{ + Resources::Resources() + { + for (auto [i, font] : std::views::enumerate(font::FONTS)) + fonts[i] = Font((void*)font.data, font.length, font::SIZE); + + for (auto [i, icon] : std::views::enumerate(icon::ICONS)) + icons[i] = Texture(icon.data, icon.length, icon.size); + + for (auto [i, shader] : std::views::enumerate(shader::SHADERS)) + shaders[i] = Shader(shader.vertex, shader.fragment); + }; } \ No newline at end of file diff --git a/src/resources.h b/src/resources.h index 912ceca..d703b4a 100644 --- a/src/resources.h +++ b/src/resources.h @@ -1,16 +1,21 @@ #pragma once -#include "PACKED.h" -#include "texture.h" +#include + +#include "font.h" +#include "icon.h" #include "shader.h" +#include "texture.h" -#define RESOURCES_TEXTURES_FREE_INFO "Freed texture resources" - -struct Resources +namespace anm2ed { - GLuint shaders[SHADER_COUNT]; - Texture atlas; -}; + class Resources + { + public: + resource::Font fonts[resource::font::COUNT]{}; + resource::Texture icons[resource::icon::COUNT]{}; + resource::Shader shaders[resource::shader::COUNT]{}; -void resources_init(Resources* self); -void resources_free(Resources* self); + Resources(); + }; +} \ No newline at end of file diff --git a/src/settings.cpp b/src/settings.cpp index 81347d9..7429bbb 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,276 +1,311 @@ #include "settings.h" -static void _settings_setting_load(Settings* self, const std::string& line) +#include "filesystem_.h" +#include "log.h" + +using namespace anm2ed::util; +using namespace glm; + +namespace anm2ed { - for (s32 i = 0; i < SETTINGS_COUNT; i++) - { - const auto& entry = SETTINGS_ENTRIES[i]; - const std::string& key = entry.key; - void* target = (u8*)self + entry.offset; + constexpr auto IMGUI_DEFAULT = R"( +# Dear ImGui +[Window][##DockSpace] +Pos=0,54 +Size=1918,1010 +Collapsed=0 - auto match_key = [&](const std::string& full) -> const char* - { - if (!line.starts_with(full)) - return nullptr; +[Window][Animation Preview] +Pos=60,62 +Size=983,691 +Collapsed=0 +DockId=0x00000003,1 - size_t p = full.size(); - while (p < line.size() && std::isspace((u8)line[p])) ++p; - if (p < line.size() && line[p] == '=') - return line.c_str() + p + 1; - return nullptr; - }; +[Window][Animations] +Pos=1451,494 +Size=459,259 +Collapsed=0 +DockId=0x0000000C,0 - const char* value = nullptr; +[Window][Events] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,0 - switch (entry.type) - { - case TYPE_INT: - if ((value = match_key(key))) { *(s32*)target = std::atoi(value); return; } - break; - case TYPE_BOOL: - if ((value = match_key(key))) { *(bool*)target = string_to_bool(value); return; } - break; - case TYPE_FLOAT: - if ((value = match_key(key))) { *(f32*)target = std::atof(value); return; } - break; - case TYPE_STRING: - if ((value = match_key(key))) { *(std::string*)target = value; return; } - break; - case TYPE_IVEC2: - { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "X"))) { v->x = std::atoi(value); return; } - if ((value = match_key(key + "Y"))) { v->y = std::atoi(value); return; } - break; - } - case TYPE_IVEC2_WH: - { - ivec2* v = (ivec2*)target; - if ((value = match_key(key + "W"))) { v->x = std::atoi(value); return; } - if ((value = match_key(key + "H"))) { v->y = std::atoi(value); return; } - break; - }; - case TYPE_VEC2: - { - vec2* v = (vec2*)target; - if ((value = match_key(key + "X"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "Y"))) { v->y = std::atof(value); return; } - break; - } - case TYPE_VEC2_WH: - { - vec2* v = (vec2*)target; - if ((value = match_key(key + "W"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "H"))) { v->y = std::atof(value); return; } - break; - }; - case TYPE_VEC3: - { - vec3* v = (vec3*)target; - if ((value = match_key(key + "R"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "G"))) { v->y = std::atof(value); return; } - if ((value = match_key(key + "B"))) { v->z = std::atof(value); return; } - break; - } - case TYPE_VEC4: - { - vec4* v = (vec4*)target; - if ((value = match_key(key + "R"))) { v->x = std::atof(value); return; } - if ((value = match_key(key + "G"))) { v->y = std::atof(value); return; } - if ((value = match_key(key + "B"))) { v->z = std::atof(value); return; } - if ((value = match_key(key + "A"))) { v->w = std::atof(value); return; } - break; - } - default: - break; - } - } +[Window][Frame Properties] +Pos=1045,62 +Size=404,399 +Collapsed=0 +DockId=0x00000007,0 - log_warning(std::format(SETTINGS_VALUE_INIT_WARNING, line)); -} +[Window][Layers] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,1 -std::string settings_path_get(void) -{ - std::string filePath = preferences_path_get() + SETTINGS_PATH; - return filePath; -} +[Window][Nulls] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,2 -static void _settings_setting_write(Settings* self, std::ostream& out, SettingsEntry entry) -{ - u8* selfPointer = (u8*)self; - std::string value; +[Window][Onionskin] +Pos=8,755 +Size=1902,301 +Collapsed=0 +DockId=0x00000006,1 - switch (entry.type) - { - case TYPE_INT: - value = std::format("{}", *(s32*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_BOOL: - value = std::format("{}", *(bool*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_FLOAT: - value = std::format("{:.3f}", *(f32*)(selfPointer + entry.offset)); - out << entry.key << "=" << value << "\n"; - break; - case TYPE_STRING: - { - const std::string data = *reinterpret_cast(selfPointer + entry.offset); - if (!data.empty()) - out << entry.key << "=" << data.c_str() << "\n"; - break; - } - case TYPE_IVEC2: - { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << data->x << "\n"; - out << entry.key << "Y=" << data->y << "\n"; - break; - } - case TYPE_IVEC2_WH: - { - ivec2* data = (ivec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << data->x << "\n"; - out << entry.key << "H=" << data->y << "\n"; - break; - } - case TYPE_VEC2: - { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "X=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "Y=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC2_WH: - { - vec2* data = (vec2*)(selfPointer + entry.offset); - out << entry.key << "W=" << std::format(SETTINGS_FLOAT_FORMAT, data->x) << "\n"; - out << entry.key << "H=" << std::format(SETTINGS_FLOAT_FORMAT, data->y) << "\n"; - break; - } - case TYPE_VEC3: - { - vec3* data = (vec3*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - break; - } - case TYPE_VEC4: - { - vec4* data = (vec4*)(selfPointer + entry.offset); - out << entry.key << "R=" << std::format(SETTINGS_FLOAT_FORMAT, data->r) << "\n"; - out << entry.key << "G=" << std::format(SETTINGS_FLOAT_FORMAT, data->g) << "\n"; - out << entry.key << "B=" << std::format(SETTINGS_FLOAT_FORMAT, data->b) << "\n"; - out << entry.key << "A=" << std::format(SETTINGS_FLOAT_FORMAT, data->a) << "\n"; - break; - } - default: - break; - } -} +[Window][Spritesheet Editor] +Pos=60,62 +Size=983,691 +Collapsed=0 +DockId=0x00000003,0 -void settings_save(Settings* self) -{ - const std::string path = settings_path_get(); - const std::filesystem::path filesystemPath(path); - const std::filesystem::path directory = filesystemPath.parent_path(); +[Window][Spritesheets] +Pos=1451,62 +Size=459,430 +Collapsed=0 +DockId=0x0000000B,0 - if (!directory.empty()) - { - std::error_code errorCode; - std::filesystem::create_directories(directory, errorCode); - if (errorCode) - { - log_error(std::format(SETTINGS_DIRECTORY_ERROR, directory.string(), errorCode.message())); - return; - } - } +[Window][Tools] +Pos=8,62 +Size=50,691 +Collapsed=0 +DockId=0x00000001,0 - std::string data; - if (std::filesystem::exists(filesystemPath)) - { - if (std::ifstream in(path, std::ios::binary); in) - data.assign(std::istreambuf_iterator(in), std::istreambuf_iterator()); - } +[Window][Timeline] +Pos=8,755 +Size=1902,301 +Collapsed=0 +DockId=0x00000006,0 - std::filesystem::path temp = filesystemPath; - temp += SETTINGS_TEMPORARY_EXTENSION; +[Window][Sounds] +Pos=1045,463 +Size=404,290 +Collapsed=0 +DockId=0x00000008,3 - std::ofstream out(temp, std::ios::binary | std::ios::trunc); - if (!out) - { - log_error(std::format(SETTINGS_INIT_ERROR, temp.string())); - return; - } +[Docking][Data] +DockSpace ID=0x123F8F08 Window=0x6D581B32 Pos=8,62 Size=1902,994 Split=Y Selected=0x4EFD0020 + DockNode ID=0x00000005 Parent=0x123F8F08 SizeRef=1910,691 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=50,994 Selected=0x18A5FDB9 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1850,994 Split=X Selected=0x4EFD0020 + DockNode ID=0x00000003 Parent=0x00000002 SizeRef=983,994 Selected=0x024430EF + DockNode ID=0x00000004 Parent=0x00000002 SizeRef=865,994 Split=X Selected=0x4EFD0020 + DockNode ID=0x00000009 Parent=0x00000004 SizeRef=404,497 Split=Y Selected=0xCD8384B1 + DockNode ID=0x00000007 Parent=0x00000009 SizeRef=181,399 Selected=0x754E368F + DockNode ID=0x00000008 Parent=0x00000009 SizeRef=181,290 Selected=0x8A65D963 + DockNode ID=0x0000000A Parent=0x00000004 SizeRef=459,497 Split=Y Selected=0x4EFD0020 + DockNode ID=0x0000000B Parent=0x0000000A SizeRef=710,430 CentralNode=1 Selected=0x4EFD0020 + DockNode ID=0x0000000C Parent=0x0000000A SizeRef=710,259 Selected=0xC1986EE2 + DockNode ID=0x00000006 Parent=0x123F8F08 SizeRef=1910,301 Selected=0x4F89F0DC +)"; - out << SETTINGS_SECTION << "\n"; - for (s32 i = 0; i < SETTINGS_COUNT; i++) - _settings_setting_write(self, out, SETTINGS_ENTRIES[i]); - - out << "\n" << SETTINGS_SECTION_IMGUI << "\n"; - out << data; - - out.flush(); - - if (!out.good()) - { - log_error(std::format(SETTINGS_SAVE_ERROR, temp.string())); - return; - } - - out.close(); - - std::error_code errorCode; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) - { - // Windows can block rename if target exists; try remove+rename - std::filesystem::remove(filesystemPath, errorCode); - errorCode = {}; - std::filesystem::rename(temp, filesystemPath, errorCode); - if (errorCode) - { - log_error(std::format(SETTINGS_SAVE_FINALIZE_ERROR, filesystemPath.string(), errorCode.message())); - std::filesystem::remove(temp); - return; - } - } - - log_info(std::format(SETTINGS_SAVE_INFO, path)); -} - -void settings_init(Settings* self) -{ - const std::string path = settings_path_get(); - std::ifstream file(path, std::ios::binary); - - if (file) - log_info(std::format(SETTINGS_INIT_INFO, path)); + Settings::Settings(const std::string& path) + { + if (filesystem::path_is_exist(path)) + logger.info(std::format("Using settings from: {}", path)); else { - log_warning(std::format(SETTINGS_INIT_WARNING, path)); - settings_save(self); - std::ofstream out(path, std::ios::binary | std::ios::app); - out << SETTINGS_IMGUI_DEFAULT; - out.flush(); - out.close(); - file.open(path, std::ios::binary); + logger.warning("Settings file does not exist; using default"); + save(path, IMGUI_DEFAULT); } - std::string line; - bool inSettingsSection = false; + std::ifstream file(path); + if (!file.is_open()) + { + logger.error(std::format("Failed to open settings file: {}", path)); + return; + } + + std::string line{}; + + auto stream_assign = [](auto& dest, std::istringstream& ss) { ss >> dest; }; + + auto value_set = [&](auto& dest, std::istringstream& ss) + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + { + std::string val; + stream_assign(val, ss); + dest = (val == "true" || val == "1"); + } + else if constexpr (std::is_same_v) + std::getline(ss, dest); + else + stream_assign(dest, ss); + }; + + auto entry_load = + [&](const std::string& key, std::istringstream& ss, const std::string& name, auto& value, std::string_view type) + { + using T = std::decay_t; + + auto is_match = [&](const char* suffix) { return key == name + suffix; }; + + if constexpr (std::is_same_v || std::is_same_v) + { + if (type.ends_with("_WH")) + { + if (is_match("W")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("H")) + { + stream_assign(value.y, ss); + return true; + } + } + else + { + if (is_match("X")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("Y")) + { + stream_assign(value.y, ss); + return true; + } + } + } + else if constexpr (std::is_same_v) + { + if (is_match("R")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("G")) + { + stream_assign(value.y, ss); + return true; + } + if (is_match("B")) + { + stream_assign(value.z, ss); + return true; + } + } + else if constexpr (std::is_same_v) + { + if (is_match("R")) + { + stream_assign(value.x, ss); + return true; + } + if (is_match("G")) + { + stream_assign(value.y, ss); + return true; + } + if (is_match("B")) + { + stream_assign(value.z, ss); + return true; + } + if (is_match("A")) + { + stream_assign(value.w, ss); + return true; + } + } + else + { + if (key == name) + { + value_set(value, ss); + return true; + } + } + + return false; + }; while (std::getline(file, line)) { - if (line == SETTINGS_SECTION) - { - inSettingsSection = true; - continue; - } - if (line.empty()) continue; - if (line == SETTINGS_SECTION_IMGUI) break; - if (inSettingsSection) _settings_setting_load(self, line); + if (line == "[Settings]" || line.empty()) continue; + if (line == "# Dear ImGui") break; + + auto eq = line.find('='); + if (eq == std::string::npos) continue; + + auto key = line.substr(0, eq); + std::istringstream ss(line.substr(eq + 1)); + +#define X(symbol, name, string, type, ...) \ + if (entry_load(key, ss, #name, name, #type)) continue; + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS +#undef X } + + file.close(); + } + + void Settings::save(const std::string& path, const std::string& imguiData) + { + std::ofstream file(path, std::ios::out | std::ios::binary); + file << "[Settings]\n"; + + auto value_save = [&](const std::string& key, const auto& value) + { + using T = std::decay_t; + + if constexpr (std::is_same_v) + file << key << "=" << (value ? "true" : "false") << "\n"; + else + file << key << "=" << value << "\n"; + }; + auto entry_save = [&](const std::string& name, const auto& value, const std::string_view type) + { + using T = std::decay_t; + + if constexpr (std::is_same_v || std::is_same_v) + { + if (type.ends_with("_WH")) + { + value_save(name + "W", value.x); + value_save(name + "H", value.y); + } + else + { + value_save(name + "X", value.x); + value_save(name + "Y", value.y); + } + } + else if constexpr (std::is_same_v) + { + value_save(name + "R", value.x); + value_save(name + "G", value.y); + value_save(name + "B", value.z); + } + else if constexpr (std::is_same_v) + { + value_save(name + "R", value.x); + value_save(name + "G", value.y); + value_save(name + "B", value.z); + value_save(name + "A", value.w); + } + else + value_save(name, value); + }; + +#define X(symbol, name, string, type, ...) entry_save(#name, name, #type); + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS +#undef X + + file + << "\n# Dear ImGui\n" + << imguiData; + + file.flush(); + file.close(); + } } \ No newline at end of file diff --git a/src/settings.h b/src/settings.h index d56edd9..db1ac02 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,355 +1,262 @@ #pragma once -#include "anm2.h" +#include + +#include + +#include "anm2/anm2.h" #include "render.h" -#include "tool.h" - -#define SETTINGS_SECTION "[Settings]" -#define SETTINGS_SECTION_IMGUI "# Dear ImGui" -#define SETTINGS_INIT_WARNING "Unable to read settings file: {}; using default settings" -#define SETTINGS_INIT_ERROR "Unable to read settings file: {}" -#define SETTINGS_SAVE_ERROR "Failed to write settings file: {}" -#define SETTINGS_SAVE_FINALIZE_ERROR "Failed to write settings file: {} ({})" -#define SETTINGS_VALUE_INIT_WARNING "Unknown setting: {}" -#define SETTINGS_FLOAT_FORMAT "{:.3f}" -#define SETTINGS_INIT_INFO "Initialized settings from: {}" -#define SETTINGS_DIRECTORY_ERROR "Failed to create settings directory: {} ({})" -#define SETTINGS_SAVE_INFO "Saved settings to: {}" - -#define SETTINGS_FOLDER "anm2ed" -#define SETTINGS_PATH "settings.ini" -#define SETTINGS_TEMPORARY_EXTENSION ".tmp" +#include "types.h" +namespace anm2ed +{ #ifdef _WIN32 -#define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "C:\\ffmpeg\\bin\\ffmpeg.exe" + constexpr auto FFMPEG_PATH_DEFAULT = "C:\\ffmpeg\\bin\\ffmpeg.exe"; #else -#define SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT "/usr/bin/ffmpeg" + constexpr auto FFMPEG_PATH_DEFAULT = "/usr/bin/ffmpeg"; #endif -#define SETTINGS_LIST \ - /* name, symbol, type, defaultValue */ \ - X(windowSize, WINDOW_SIZE, TYPE_IVEC2_WH, {1600, 900}) \ - X(isVsync, IS_VSYNC, TYPE_BOOL, true) \ - \ - X(hotkeyCenterView, HOTKEY_CENTER_VIEW, TYPE_STRING, "Home") \ - X(hotkeyFit, HOTKEY_FIT, TYPE_STRING, "F") \ - X(hotkeyZoomIn, HOTKEY_ZOOM_IN, TYPE_STRING, "Ctrl++") \ - X(hotkeyZoomOut, HOTKEY_ZOOM_OUT, TYPE_STRING, "Ctrl+-") \ - X(hotkeyPlayPause, HOTKEY_PLAY_PAUSE, TYPE_STRING, "Space") \ - X(hotkeyOnionskin, HOTKEY_ONIONSKIN, TYPE_STRING, "O") \ - X(hotkeyNew, HOTKEY_NEW, TYPE_STRING, "Ctrl+N") \ - X(hotkeyOpen, HOTKEY_OPEN, TYPE_STRING, "Ctrl+O") \ - X(hotkeySave, HOTKEY_SAVE, TYPE_STRING, "Ctrl+S") \ - X(hotkeySaveAs, HOTKEY_SAVE_AS, TYPE_STRING, "Ctrl+Shift+S") \ - X(hotkeyExit, HOTKEY_EXIT, TYPE_STRING, "Alt+F4") \ - X(hotkeyPan, HOTKEY_PAN, TYPE_STRING, "P") \ - X(hotkeyMove, HOTKEY_MOVE, TYPE_STRING, "V") \ - X(hotkeyRotate, HOTKEY_ROTATE, TYPE_STRING, "R") \ - X(hotkeyScale, HOTKEY_SCALE, TYPE_STRING, "S") \ - X(hotkeyCrop, HOTKEY_CROP, TYPE_STRING, "C") \ - X(hotkeyDraw, HOTKEY_DRAW, TYPE_STRING, "B") \ - X(hotkeyErase, HOTKEY_ERASE, TYPE_STRING, "E") \ - X(hotkeyColorPicker, HOTKEY_COLOR_PICKER, TYPE_STRING, "I") \ - X(hotkeyUndo, HOTKEY_UNDO, TYPE_STRING, "Ctrl+Z") \ - X(hotkeyRedo, HOTKEY_REDO, TYPE_STRING, "Ctrl+Shift+Z") \ - X(hotkeyCopy, HOTKEY_COPY, TYPE_STRING, "Ctrl+C") \ - X(hotkeyCut, HOTKEY_CUT, TYPE_STRING, "Ctrl+X") \ - X(hotkeyPaste, HOTKEY_PASTE, TYPE_STRING, "Ctrl+V") \ - \ - X(playbackIsLoop, PLAYBACK_IS_LOOP, TYPE_BOOL, true) \ - X(playbackIsClampPlayhead,PLAYBACK_IS_CLAMP_PLAYHEAD, TYPE_BOOL, true) \ - \ - X(changeIsCrop, CHANGE_IS_CROP, TYPE_BOOL, false) \ - X(changeIsSize, CHANGE_IS_SIZE, TYPE_BOOL, false) \ - X(changeIsPosition, CHANGE_IS_POSITION, TYPE_BOOL, false) \ - X(changeIsPivot, CHANGE_IS_PIVOT, TYPE_BOOL, false) \ - X(changeIsScale, CHANGE_IS_SCALE, TYPE_BOOL, false) \ - X(changeIsRotation, CHANGE_IS_ROTATION, TYPE_BOOL, false) \ - X(changeIsDelay, CHANGE_IS_DELAY, TYPE_BOOL, false) \ - X(changeIsTint, CHANGE_IS_TINT, TYPE_BOOL, false) \ - X(changeIsColorOffset, CHANGE_IS_COLOR_OFFSET, TYPE_BOOL, false) \ - X(changeIsVisibleSet, CHANGE_IS_VISIBLE_SET, TYPE_BOOL, false) \ - X(changeIsInterpolatedSet,CHANGE_IS_INTERPOLATED_SET, TYPE_BOOL, false) \ - X(changeIsFromSelectedFrame,CHANGE_IS_FROM_SELECTED_FRAME,TYPE_BOOL, false) \ - X(changeCrop, CHANGE_CROP, TYPE_VEC2, {}) \ - X(changeSize, CHANGE_SIZE, TYPE_VEC2, {}) \ - X(changePosition, CHANGE_POSITION, TYPE_VEC2, {}) \ - X(changePivot, CHANGE_PIVOT, TYPE_VEC2, {}) \ - X(changeScale, CHANGE_SCALE, TYPE_VEC2, {}) \ - X(changeRotation, CHANGE_ROTATION, TYPE_FLOAT, 0.0f) \ - X(changeDelay, CHANGE_DELAY, TYPE_INT, 0) \ - X(changeTint, CHANGE_TINT, TYPE_VEC4, {}) \ - X(changeColorOffset, CHANGE_COLOR_OFFSET, TYPE_VEC3, {}) \ - X(changeIsVisible, CHANGE_IS_VISIBLE, TYPE_BOOL, false) \ - X(changeIsInterpolated, CHANGE_IS_INTERPOLATED, TYPE_BOOL, false) \ - X(changeNumberFrames, CHANGE_NUMBER_FRAMES, TYPE_INT, 1) \ - \ - X(scaleValue, SCALE_VALUE, TYPE_FLOAT, 1.0f) \ - \ - X(previewIsAxes, PREVIEW_IS_AXES, TYPE_BOOL, true) \ - X(previewIsGrid, PREVIEW_IS_GRID, TYPE_BOOL, true) \ - X(previewIsRootTransform, PREVIEW_IS_ROOT_TRANSFORM, TYPE_BOOL, true) \ - X(previewIsTriggers, PREVIEW_IS_TRIGGERS, TYPE_BOOL, true) \ - X(previewIsPivots, PREVIEW_IS_PIVOTS, TYPE_BOOL, false) \ - X(previewIsIcons, PREVIEW_IS_ICONS, TYPE_BOOL, true) \ - X(previewIsBorder, PREVIEW_IS_BORDER, TYPE_BOOL, false) \ - X(previewIsAltIcons, PREVIEW_IS_ALT_ICONS, TYPE_BOOL, false) \ - X(previewOverlayTransparency,PREVIEW_OVERLAY_TRANSPARENCY,TYPE_FLOAT, 255.0f) \ - X(previewZoom, PREVIEW_ZOOM, TYPE_FLOAT, 200.0f) \ - X(previewPan, PREVIEW_PAN, TYPE_VEC2, {}) \ - X(previewGridSize, PREVIEW_GRID_SIZE, TYPE_IVEC2, {32,32}) \ - X(previewGridOffset, PREVIEW_GRID_OFFSET, TYPE_IVEC2, {}) \ - X(previewGridColor, PREVIEW_GRID_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(previewAxesColor, PREVIEW_AXES_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(previewBackgroundColor, PREVIEW_BACKGROUND_COLOR, TYPE_VEC4, {0.113,0.184,0.286,1.0}) \ - \ - X(propertiesIsRound, PROPERTIES_IS_ROUND, TYPE_BOOL, false) \ - \ - X(generateStartPosition, GENERATE_START_POSITION, TYPE_IVEC2, {}) \ - X(generateSize, GENERATE_SIZE, TYPE_IVEC2, {64,64}) \ - X(generatePivot, GENERATE_PIVOT, TYPE_IVEC2, {32,32}) \ - X(generateRows, GENERATE_ROWS, TYPE_INT, 4) \ - X(generateColumns, GENERATE_COLUMNS, TYPE_INT, 4) \ - X(generateCount, GENERATE_COUNT, TYPE_INT, 16) \ - X(generateDelay, GENERATE_DELAY, TYPE_INT, 1) \ - \ - X(editorIsGrid, EDITOR_IS_GRID, TYPE_BOOL, true) \ - X(editorIsGridSnap, EDITOR_IS_GRID_SNAP, TYPE_BOOL, true) \ - X(editorIsBorder, EDITOR_IS_BORDER, TYPE_BOOL, true) \ - X(editorZoom, EDITOR_ZOOM, TYPE_FLOAT, 200.0f) \ - X(editorPan, EDITOR_PAN, TYPE_VEC2, {0.0,0.0}) \ - X(editorGridSize, EDITOR_GRID_SIZE, TYPE_IVEC2, {32,32}) \ - X(editorGridOffset, EDITOR_GRID_OFFSET, TYPE_IVEC2, {32,32}) \ - X(editorGridColor, EDITOR_GRID_COLOR, TYPE_VEC4, {1.0,1.0,1.0,0.125}) \ - X(editorBackgroundColor, EDITOR_BACKGROUND_COLOR, TYPE_VEC4, {0.113,0.184,0.286,1.0}) \ - \ - X(mergeType, MERGE_TYPE, TYPE_INT, ANM2_MERGE_APPEND) \ - X(mergeIsDeleteAnimationsAfter,MERGE_IS_DELETE_ANIMATIONS_AFTER,TYPE_BOOL, false) \ - \ - X(bakeInterval, BAKE_INTERVAL, TYPE_INT, 1) \ - X(bakeIsRoundScale, BAKE_IS_ROUND_SCALE, TYPE_BOOL, true) \ - X(bakeIsRoundRotation, BAKE_IS_ROUND_ROTATION, TYPE_BOOL, true) \ - \ - X(timelineAddItemType, TIMELINE_ADD_ITEM_TYPE, TYPE_INT, ANM2_LAYER) \ - X(timelineIsShowUnused, TIMELINE_IS_SHOW_UNUSED, TYPE_BOOL, true) \ - \ - X(onionskinIsEnabled, ONIONSKIN_IS_ENABLED, TYPE_BOOL, false) \ - X(onionskinDrawOrder, ONIONSKIN_DRAW_ORDER, TYPE_INT, ONIONSKIN_BELOW) \ - X(onionskinBeforeCount, ONIONSKIN_BEFORE_COUNT, TYPE_INT, 0) \ - X(onionskinAfterCount, ONIONSKIN_AFTER_COUNT, TYPE_INT, 0) \ - X(onionskinBeforeColorOffset,ONIONSKIN_BEFORE_COLOR_OFFSET,TYPE_VEC3, COLOR_RED) \ - X(onionskinAfterColorOffset, ONIONSKIN_AFTER_COLOR_OFFSET,TYPE_VEC3, COLOR_BLUE) \ - \ - X(tool, TOOL, TYPE_INT, TOOL_PAN) \ - X(toolColor, TOOL_COLOR, TYPE_VEC4, {1.0,1.0,1.0,1.0}) \ - \ - X(renderType, RENDER_TYPE, TYPE_INT, RENDER_PNG) \ - X(renderPath, RENDER_PATH, TYPE_STRING, ".") \ - X(renderFormat, RENDER_FORMAT, TYPE_STRING, "{}.png") \ - X(renderIsUseAnimationBounds,RENDER_IS_USE_ANIMATION_BOUNDS,TYPE_BOOL, true) \ - X(renderIsTransparent, RENDER_IS_TRANSPARENT, TYPE_BOOL, true) \ - X(renderScale, RENDER_SCALE, TYPE_FLOAT, 1.0f) \ - X(renderFFmpegPath, RENDER_FFMPEG_PATH, TYPE_STRING, SETTINGS_RENDER_FFMPEG_PATH_VALUE_DEFAULT) +#define SETTINGS_TYPES \ + X(INT, int) \ + X(BOOL, bool) \ + X(FLOAT, float) \ + X(STRING, std::string) \ + X(IVEC2, glm::ivec2) \ + X(IVEC2_WH, glm::ivec2) \ + X(VEC2, glm::vec2) \ + X(VEC2_WH, glm::vec2) \ + X(VEC3, glm::vec3) \ + X(VEC4, glm::vec4) -#define X(name, symbol, type, ...) \ -const inline DATATYPE_TO_CTYPE(type) SETTINGS_##symbol##_DEFAULT = __VA_ARGS__; -SETTINGS_LIST + enum Type + { +#define X(name, type) name, + SETTINGS_TYPES +#undef X + }; + +#define X(name, type) using TYPE_##name = type; + SETTINGS_TYPES #undef X -struct Settings -{ - #define X(name, symbol, type, ...) \ - DATATYPE_TO_CTYPE(type) name = SETTINGS_##symbol##_DEFAULT; - SETTINGS_LIST - #undef X -}; - -struct SettingsEntry -{ - std::string key; - DataType type; - s32 offset; -}; +#define SETTINGS_MEMBERS \ + /* Symbol / Name / String / Type / Default */ \ + X(WINDOW_SIZE, windowSize, "Window Size", IVEC2_WH, {1600, 900}) \ + X(IS_VSYNC, isVsync, "Vsync", BOOL, true) \ + X(UI_SCALE, uiScale, "UI Scale", FLOAT, 1.0f) \ + \ + X(FILE_IS_AUTOSAVE, fileIsAutosave, "Autosave", BOOL, true) \ + X(FILE_AUTOSAVE_TIME, fileAutosaveTime, "Autosave Time", INT, 1) \ + \ + X(KEYBOARD_REPEAT_DELAY, keyboardRepeatDelay, "Repeat Delay", FLOAT, 0.300f) \ + X(KEYBOARD_REPEAT_RATE, keyboardRepeatRate, "Repeat Rate", FLOAT, 0.050f) \ + \ + X(VIEW_ZOOM_STEP, viewZoomStep, "Zoom Step", FLOAT, 50.0f) \ + \ + X(PLAYBACK_IS_LOOP, playbackIsLoop, "Loop", BOOL, true) \ + X(PLAYBACK_IS_CLAMP_PLAYHEAD, playbackIsClampPlayhead, "Clamp Playhead", BOOL, true) \ + \ + X(CHANGE_IS_CROP, changeIsCrop, "##Is Crop", BOOL, false) \ + X(CHANGE_IS_SIZE, changeIsSize, "##Is Size", BOOL, false) \ + X(CHANGE_IS_POSITION, changeIsPosition, "##Is Position", BOOL, false) \ + X(CHANGE_IS_PIVOT, changeIsPivot, "##Is Pivot", BOOL, false) \ + X(CHANGE_IS_SCALE, changeIsScale, "##Is Scale", BOOL, false) \ + X(CHANGE_IS_ROTATION, changeIsRotation, "##Is Rotation", BOOL, false) \ + X(CHANGE_IS_DELAY, changeIsDelay, "##Is Delay", BOOL, false) \ + X(CHANGE_IS_TINT, changeIsTint, "##Is Tint", BOOL, false) \ + X(CHANGE_IS_COLOR_OFFSET, changeIsColorOffset, "##Is Color Offset", BOOL, false) \ + X(CHANGE_IS_VISIBLE_SET, changeIsVisibleSet, "##Is Visible", BOOL, false) \ + X(CHANGE_IS_INTERPOLATED_SET, changeIsInterpolatedSet, "##Is Interpolated", BOOL, false) \ + X(CHANGE_CROP, changeCrop, "Crop", VEC2, {}) \ + X(CHANGE_SIZE, changeSize, "Size", VEC2, {}) \ + X(CHANGE_POSITION, changePosition, "Position", VEC2, {}) \ + X(CHANGE_PIVOT, changePivot, "Pivot", VEC2, {}) \ + X(CHANGE_SCALE, changeScale, "Scale", VEC2, {}) \ + X(CHANGE_ROTATION, changeRotation, "Rotation", FLOAT, 0.0f) \ + X(CHANGE_DELAY, changeDelay, "Delay", INT, 0) \ + X(CHANGE_TINT, changeTint, "Tint", VEC4, {}) \ + X(CHANGE_COLOR_OFFSET, changeColorOffset, "Color Offset", VEC3, {}) \ + X(CHANGE_IS_VISIBLE, changeIsVisible, "Visible", BOOL, false) \ + X(CHANGE_IS_INTERPOLATED, changeIsInterpolated, "Interpolated", BOOL, false) \ + X(CHANGE_NUMBER_FRAMES, changeNumberFrames, "Frame Count", INT, 1) \ + X(CHANGE_IS_FROM_SELECTED_FRAME, changeIsFromSelectedFrame, "From Selected Frame", BOOL, false) \ + \ + X(SCALE_VALUE, scaleValue, "Scale", FLOAT, 1.0f) \ + \ + X(PREVIEW_IS_AXES, previewIsAxes, "Axes", BOOL, true) \ + X(PREVIEW_IS_GRID, previewIsGrid, "Grid", BOOL, true) \ + X(PREVIEW_IS_ROOT_TRANSFORM, previewIsRootTransform, "Root Transform", BOOL, true) \ + X(PREVIEW_IS_PIVOTS, previewIsPivots, "Pivots", BOOL, false) \ + X(PREVIEW_IS_BORDER, previewIsBorder, "Border", BOOL, false) \ + X(PREVIEW_IS_ALT_ICONS, previewIsAltIcons, "Alt Icons", BOOL, false) \ + X(PREVIEW_OVERLAY_TRANSPARENCY, previewOverlayTransparency, "Alpha", FLOAT, 255) \ + X(PREVIEW_START_ZOOM, previewStartZoom, "Start Zoom", FLOAT, 200.0f) \ + X(PREVIEW_GRID_SIZE, previewGridSize, "Size", IVEC2, {32, 32}) \ + X(PREVIEW_GRID_OFFSET, previewGridOffset, "Offset", IVEC2, {}) \ + X(PREVIEW_GRID_COLOR, previewGridColor, "Color", VEC4, {1.0f, 1.0f, 1.0f, 0.125f}) \ + X(PREVIEW_AXES_COLOR, previewAxesColor, "Color", VEC4, {1.0f, 1.0f, 1.0f, 0.125f}) \ + X(PREVIEW_BACKGROUND_COLOR, previewBackgroundColor, "Background Color", VEC4, {0.113f, 0.184f, 0.286f, 1.0f}) \ + \ + X(PROPERTIES_IS_ROUND, propertiesIsRound, "Round", BOOL, false) \ + \ + X(GENERATE_START_POSITION, generateStartPosition, "Start Position", IVEC2, {}) \ + X(GENERATE_SIZE, generateSize, "Size", IVEC2, {64, 64}) \ + X(GENERATE_PIVOT, generatePivot, "Pivot", IVEC2, {32, 32}) \ + X(GENERATE_ROWS, generateRows, "Rows", INT, 4) \ + X(GENERATE_COLUMNS, generateColumns, "Columns", INT, 4) \ + X(GENERATE_COUNT, generateCount, "Count", INT, 16) \ + X(GENERATE_DELAY, generateDelay, "Delay", INT, 1) \ + X(GENERATE_ZOOM, generateZoom, "Zoom", FLOAT, 100.0f) \ + \ + X(EDITOR_IS_GRID, editorIsGrid, "Grid", BOOL, true) \ + X(EDITOR_IS_GRID_SNAP, editorIsGridSnap, "Snap", BOOL, true) \ + X(EDITOR_IS_BORDER, editorIsBorder, "Border", BOOL, true) \ + X(EDITOR_START_ZOOM, editorStartZoom, "Zoom", FLOAT, 200.0f) \ + X(EDITOR_SIZE, editorSize, "Size", IVEC2_WH, {1200, 600}) \ + X(EDITOR_GRID_SIZE, editorGridSize, "Grid Size", IVEC2, {32, 32}) \ + X(EDITOR_GRID_OFFSET, editorGridOffset, "Offset", IVEC2, {32, 32}) \ + X(EDITOR_GRID_COLOR, editorGridColor, "Color", VEC4, {1.0, 1.0, 1.0, 0.125}) \ + X(EDITOR_BACKGROUND_COLOR, editorBackgroundColor, "Background Color", VEC4, {0.113, 0.184, 0.286, 1.0}) \ + \ + X(MERGE_TYPE, mergeType, "Type", INT, 0) \ + X(MERGE_IS_DELETE_ANIMATIONS_AFTER, mergeIsDeleteAnimationsAfter, "Delete Animations After", BOOL, false) \ + \ + X(BAKE_INTERVAL, bakeInterval, "Interval", INT, 1) \ + X(BAKE_IS_ROUND_SCALE, bakeIsRoundScale, "Round Scale", BOOL, true) \ + X(BAKE_IS_ROUND_ROTATION, bakeIsRoundRotation, "Round Rotation", BOOL, true) \ + \ + X(TIMELINE_ADD_ITEM_TYPE, timelineAddItemType, "Add Item Type", INT, anm2::LAYER) \ + X(TIMELINE_ADD_ITEM_LOCALITY, timelineAddItemLocale, "Add Item Locale", INT, types::locale::GLOBAL) \ + X(TIMELINE_ADD_ITEM_SOURCE, timelineAddItemSource, "Add Item Source", INT, types::source::NEW) \ + X(TIMELINE_IS_SHOW_UNUSED, timelineIsShowUnused, "##Show Unused", BOOL, true) \ + X(TIMELINE_IS_ONLY_SHOW_LAYERS, timelineIsOnlyShowLayers, "##Only Show Layers", BOOL, true) \ + X(TIMELINE_IS_SOUND, timelineIsSound, "Sound", BOOL, true) \ + \ + X(ONIONSKIN_IS_ENABLED, onionskinIsEnabled, "Enabled", BOOL, false) \ + X(ONIONSKIN_DRAW_ORDER, onionskinDrawOrder, "Draw Order", INT, 0) \ + X(ONIONSKIN_BEFORE_COUNT, onionskinBeforeCount, "Frames", INT, 0) \ + X(ONIONSKIN_AFTER_COUNT, onionskinAfterCount, "Frames", INT, 0) \ + X(ONIONSKIN_BEFORE_COLOR, onionskinBeforeColor, "Color", VEC3, types::color::RED) \ + X(ONIONSKIN_AFTER_COLOR, onionskinAfterColor, "Color", VEC3, types::color::BLUE) \ + \ + X(TOOL, tool, "##Tool", INT, 0) \ + X(TOOL_COLOR, toolColor, "##Color", VEC4, {1.0, 1.0, 1.0, 1.0}) \ + \ + X(RENDER_TYPE, renderType, "Output", INT, render::PNGS) \ + X(RENDER_PATH, renderPath, "Path", STRING, ".") \ + X(RENDER_FORMAT, renderFormat, "Format", STRING, "{}.png") \ + X(RENDER_IS_RAW_ANIMATION, renderIsRawAnimation, "Raw Animation", BOOL, true) \ + X(RENDER_SCALE, renderScale, "Scale", FLOAT, 1.0f) \ + X(RENDER_FFMPEG_PATH, renderFFmpegPath, "FFmpeg Path", STRING, FFMPEG_PATH_DEFAULT) -const inline SettingsEntry SETTINGS_ENTRIES[] = -{ - #define X(name, symbol, type, ...) \ - { #name, type, offsetof(Settings, name) }, - SETTINGS_LIST - #undef X -}; +#define SETTINGS_SHORTCUTS \ + /* Symbol / Name / String / Type / Default */ \ + X(SHORTCUT_CENTER_VIEW, shortcutCenterView, "Center View", STRING, "Home") \ + X(SHORTCUT_FIT, shortcutFit, "Fit", STRING, "F") \ + X(SHORTCUT_ZOOM_IN, shortcutZoomIn, "Zoom In", STRING, "Ctrl+Equal") \ + X(SHORTCUT_ZOOM_OUT, shortcutZoomOut, "Zoom Out", STRING, "Ctrl+Minus") \ + X(SHORTCUT_PLAY_PAUSE, shortcutPlayPause, "Play/Pause", STRING, "Space") \ + X(SHORTCUT_ONIONSKIN, shortcutOnionskin, "Onionskin", STRING, "O") \ + X(SHORTCUT_NEW, shortcutNew, "New", STRING, "Ctrl+N") \ + X(SHORTCUT_OPEN, shortcutOpen, "Open", STRING, "Ctrl+O") \ + X(SHORTCUT_CLOSE, shortcutClose, "Close", STRING, "Ctrl+W") \ + X(SHORTCUT_SAVE, shortcutSave, "Save", STRING, "Ctrl+S") \ + X(SHORTCUT_SAVE_AS, shortcutSaveAs, "Save As", STRING, "Ctrl+Shift+S") \ + X(SHORTCUT_EXIT, shortcutExit, "Exit", STRING, "Alt+F4") \ + X(SHORTCUT_SHORTEN_FRAME, shortcutShortenFrame, "Shorten Frame", STRING, "F4") \ + X(SHORTCUT_EXTEND_FRAME, shortcutExtendFrame, "Extend Frame", STRING, "F5") \ + X(SHORTCUT_INSERT_FRAME, shortcutInsertFrame, "Insert Frame", STRING, "F6") \ + X(SHORTCUT_PREVIOUS_FRAME, shortcutPreviousFrame, "Previous Frame", STRING, "Comma") \ + X(SHORTCUT_NEXT_FRAME, shortcutNextFrame, "Next Frame", STRING, "Period") \ + X(SHORTCUT_PAN, shortcutPan, "Pan", STRING, "P") \ + X(SHORTCUT_MOVE, shortcutMove, "Move", STRING, "V") \ + X(SHORTCUT_ROTATE, shortcutRotate, "Rotate", STRING, "R") \ + X(SHORTCUT_SCALE, shortcutScale, "Scale", STRING, "S") \ + X(SHORTCUT_CROP, shortcutCrop, "Crop", STRING, "C") \ + X(SHORTCUT_DRAW, shortcutDraw, "Draw", STRING, "B") \ + X(SHORTCUT_ERASE, shortcutErase, "Erase", STRING, "E") \ + X(SHORTCUT_COLOR_PICKER, shortcutColorPicker, "Color Picker", STRING, "I") \ + X(SHORTCUT_UNDO, shortcutUndo, "Undo", STRING, "Ctrl+Z") \ + X(SHORTCUT_REDO, shortcutRedo, "Redo", STRING, "Ctrl+Shift+Z") \ + X(SHORTCUT_COLOR, shortcutColor, "Color", STRING, "X") \ + X(SHORTCUT_COPY, shortcutCopy, "Copy", STRING, "Ctrl+C") \ + X(SHORTCUT_CUT, shortcutCut, "Cut", STRING, "Ctrl+X") \ + X(SHORTCUT_ADD, shortcutAdd, "Add", STRING, "Insert") \ + X(SHORTCUT_REMOVE, shortcutRemove, "Remove", STRING, "Delete") \ + X(SHORTCUT_DUPLICATE, shortcutDuplicate, "Duplicate", STRING, "Ctrl+J") \ + X(SHORTCUT_DEFAULT, shortcutDefault, "Default", STRING, "Home") \ + X(SHORTCUT_MERGE, shortcutMerge, "Merge", STRING, "Ctrl+E") \ + X(SHORTCUT_PASTE, shortcutPaste, "Paste", STRING, "Ctrl+V") \ + X(SHORTCUT_SELECT_ALL, shortcutSelectAll, "Select All", STRING, "Ctrl+A") \ + X(SHORTCUT_SELECT_NONE, shortcutSelectNone, "Select None", STRING, "Escape") -constexpr s32 SETTINGS_COUNT = (s32)std::size(SETTINGS_ENTRIES); +#define SETTINGS_WINDOWS \ + /* Symbol / Name / String / Type / Default */ \ + X(WINDOW_ANIMATIONS, windowIsAnimations, "Animations", BOOL, true) \ + X(WINDOW_ANIMATION_PREVIEW, windowIsAnimationPreview, "Animation Preview", BOOL, true) \ + X(WINDOW_EVENTS, windowIsEvents, "Events", BOOL, true) \ + X(WINDOW_FRAME_PROPERTIES, windowIsFrameProperties, "Frame Properties", BOOL, true) \ + X(WINDOW_LAYERS, windowIsLayers, "Layers", BOOL, true) \ + X(WINDOW_NULLS, windowIsNulls, "Nulls", BOOL, true) \ + X(WINDOW_ONIONSKIN, windowIsOnionskin, "Onionskin", BOOL, true) \ + X(WINDOW_PREVIEW, windowIsSpritesheets, "Spritesheets", BOOL, true) \ + X(WINDOW_SOUNDS, windowIsSounds, "Sounds", BOOL, true) \ + X(WINDOW_SPRITESHEET_EDITOR, windowIsSpritesheetEditor, "Spritesheet Editor", BOOL, true) \ + X(WINDOW_TIMELINE, windowIsTimeline, "Timeline", BOOL, true) \ + X(WINDOW_TOOLS, windowIsTools, "Tools", BOOL, true) -#define HOTKEY_LIST \ - X(NONE, "None") \ - X(CENTER_VIEW, "Center View") \ - X(FIT, "Fit") \ - X(ZOOM_IN, "Zoom In") \ - X(ZOOM_OUT, "Zoom Out") \ - X(PLAY_PAUSE, "Play/Pause") \ - X(ONIONSKIN, "Onionskin") \ - X(NEW, "New") \ - X(OPEN, "Open") \ - X(SAVE, "Save") \ - X(SAVE_AS, "Save As") \ - X(EXIT, "Exit") \ - X(PAN, "Pan") \ - X(MOVE, "Move") \ - X(ROTATE, "Rotate") \ - X(SCALE, "Scale") \ - X(CROP, "Crop") \ - X(DRAW, "Draw") \ - X(ERASE, "Erase") \ - X(COLOR_PICKER, "Color Picker") \ - X(UNDO, "Undo") \ - X(REDO, "Redo") \ - X(COPY, "Copy") \ - X(CUT, "Cut") \ - X(PASTE, "Paste") \ - -typedef enum -{ - #define X(name, str) HOTKEY_##name, - HOTKEY_LIST - #undef X - HOTKEY_COUNT -} HotkeyType; + class Settings + { + public: +#define X(symbol, name, string, type, ...) TYPE_##type name = __VA_ARGS__; + SETTINGS_MEMBERS SETTINGS_SHORTCUTS SETTINGS_WINDOWS +#undef X -const inline char* HOTKEY_STRINGS[] = -{ - #define X(name, str) str, - HOTKEY_LIST - #undef X -}; + Settings() = default; -using HotkeyMember = std::string Settings::*; + Settings(const std::string&); + void save(const std::string&, const std::string&); + }; -const inline HotkeyMember SETTINGS_HOTKEY_MEMBERS[HOTKEY_COUNT] = -{ - nullptr, - &Settings::hotkeyCenterView, - &Settings::hotkeyFit, - &Settings::hotkeyZoomIn, - &Settings::hotkeyZoomOut, - &Settings::hotkeyPlayPause, - &Settings::hotkeyOnionskin, - &Settings::hotkeyNew, - &Settings::hotkeyOpen, - &Settings::hotkeySave, - &Settings::hotkeySaveAs, - &Settings::hotkeyExit, - &Settings::hotkeyPan, - &Settings::hotkeyMove, - &Settings::hotkeyRotate, - &Settings::hotkeyScale, - &Settings::hotkeyCrop, - &Settings::hotkeyDraw, - &Settings::hotkeyErase, - &Settings::hotkeyColorPicker, - &Settings::hotkeyUndo, - &Settings::hotkeyRedo, - &Settings::hotkeyCopy, - &Settings::hotkeyCut, - &Settings::hotkeyPaste -}; + enum ShortcutType + { +#define X(symbol, name, string, type, ...) symbol, + SETTINGS_SHORTCUTS +#undef X + SHORTCUT_COUNT + }; -const std::string SETTINGS_IMGUI_DEFAULT = R"( -# Dear ImGui -[Window][## Window] -Pos=0,32 -Size=1600,868 -Collapsed=0 + constexpr const char* SHORTCUT_STRINGS[] = { +#define X(symbol, name, string, type, ...) string, + SETTINGS_SHORTCUTS +#undef X + }; -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 + using ShortcutMember = std::string Settings::*; + constexpr ShortcutMember SHORTCUT_MEMBERS[] = { +#define X(symbol, name, string, type, ...) &Settings::name, + SETTINGS_SHORTCUTS +#undef X + }; -[Window][Tools] -Pos=8,40 -Size=38,516 -Collapsed=0 -DockId=0x0000000B,0 + enum WindowType + { +#define X(symbol, name, string, type, ...) symbol, + SETTINGS_WINDOWS +#undef X + WINDOW_COUNT + }; -[Window][Animations] -Pos=1289,307 -Size=303,249 -Collapsed=0 -DockId=0x0000000A,0 + constexpr const char* WINDOW_STRINGS[] = { +#define X(symbol, name, string, type, ...) string, + SETTINGS_WINDOWS +#undef X + }; -[Window][Events] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,2 - -[Window][Spritesheets] -Pos=1289,40 -Size=303,265 -Collapsed=0 -DockId=0x00000009,0 - -[Window][Animation Preview] -Pos=48,40 -Size=907,516 -Collapsed=0 -DockId=0x0000000C,0 - -[Window][Spritesheet Editor] -Pos=48,40 -Size=907,516 -Collapsed=0 -DockId=0x0000000C,1 - -[Window][Timeline] -Pos=8,558 -Size=1584,334 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Frame Properties] -Pos=957,40 -Size=330,222 -Collapsed=0 -DockId=0x00000007,0 - -[Window][Onionskin] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,3 - -[Window][Layers] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,0 - -[Window][Nulls] -Pos=957,264 -Size=330,292 -Collapsed=0 -DockId=0x00000008,1 - - -[Docking][Data] -DockSpace ID=0xFC02A410 Window=0x0E46F4F7 Pos=8,40 Size=1584,852 Split=Y - DockNode ID=0x00000003 Parent=0xFC02A410 SizeRef=1902,680 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1017,1016 Split=X Selected=0x024430EF - DockNode ID=0x00000005 Parent=0x00000001 SizeRef=1264,654 Split=X Selected=0x024430EF - DockNode ID=0x0000000B Parent=0x00000005 SizeRef=38,654 Selected=0x18A5FDB9 - DockNode ID=0x0000000C Parent=0x00000005 SizeRef=1224,654 CentralNode=1 Selected=0x024430EF - DockNode ID=0x00000006 Parent=0x00000001 SizeRef=330,654 Split=Y Selected=0x754E368F - DockNode ID=0x00000007 Parent=0x00000006 SizeRef=631,293 Selected=0x754E368F - DockNode ID=0x00000008 Parent=0x00000006 SizeRef=631,385 Selected=0xCD8384B1 - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=303,1016 Split=Y Selected=0x4EFD0020 - DockNode ID=0x00000009 Parent=0x00000002 SizeRef=634,349 Selected=0x4EFD0020 - DockNode ID=0x0000000A Parent=0x00000002 SizeRef=634,329 Selected=0xC1986EE2 - DockNode ID=0x00000004 Parent=0xFC02A410 SizeRef=1902,334 Selected=0x4F89F0DC - -)"; - -void settings_save(Settings* self); -void settings_init(Settings* self); -std::string settings_path_get(void); \ No newline at end of file + using WindowMember = bool Settings::*; + static constexpr WindowMember WINDOW_MEMBERS[] = { +#define X(symbol, name, string, type, ...) &Settings::name, + SETTINGS_WINDOWS +#undef X + }; +} diff --git a/src/shader.cpp b/src/shader.cpp deleted file mode 100644 index 514265b..0000000 --- a/src/shader.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "shader.h" - -static bool _shader_compile(GLuint* self, const std::string& text) -{ - s32 isCompile; - const GLchar* source = text.c_str(); - - glShaderSource(*self, 1, &source, nullptr); - glCompileShader(*self); - glGetShaderiv(*self, GL_COMPILE_STATUS, &isCompile); - - if (!isCompile) - { - std::string compileLog(SHADER_INFO_LOG_MAX, '\0'); - glGetShaderInfoLog(*self, SHADER_INFO_LOG_MAX, nullptr, compileLog.data()); - log_error(std::format(SHADER_INIT_ERROR, *self, compileLog.c_str())); - return false; - } - - return true; -} - -// Initializes a given shader with vertex/fragment -bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment) -{ - GLuint vertexHandle; - GLuint fragmentHandle; - - vertexHandle = glCreateShader(GL_VERTEX_SHADER); - fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER); - - if (!_shader_compile(&vertexHandle, vertex) || !_shader_compile(&fragmentHandle, fragment)) - return false; - - *self = glCreateProgram(); - - glAttachShader(*self, vertexHandle); - glAttachShader(*self, fragmentHandle); - - glLinkProgram(*self); - - glDeleteShader(vertexHandle); - glDeleteShader(fragmentHandle); - - return true; -} - -void shader_free(GLuint* self) -{ - if (*self == GL_ID_NONE) return; - - glDeleteProgram(*self); -} \ No newline at end of file diff --git a/src/shader.h b/src/shader.h deleted file mode 100644 index 5b34f38..0000000 --- a/src/shader.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "log.h" - -#define SHADER_INFO_LOG_MAX 0xFF -#define SHADER_INIT_ERROR "Failed to initialize shader {}:\n{}" - -bool shader_init(GLuint* self, const std::string& vertex, const std::string& fragment); -void shader_free(GLuint* self); \ No newline at end of file diff --git a/src/snapshots.cpp b/src/snapshots.cpp index 2c8cf46..c9df201 100644 --- a/src/snapshots.cpp +++ b/src/snapshots.cpp @@ -1,77 +1,57 @@ #include "snapshots.h" -static void _snapshot_stack_push(SnapshotStack* stack, Snapshot* snapshot) +using namespace anm2ed::snapshots; + +namespace anm2ed { - if (stack->top >= SNAPSHOT_STACK_MAX) + bool SnapshotStack::is_empty() { return top == 0; } + + void SnapshotStack::push(const Snapshot& snapshot) + { + if (top >= MAX) { - for (s32 i = 0; i < SNAPSHOT_STACK_MAX - 1; i++) - stack->snapshots[i] = stack->snapshots[i + 1]; - stack->top = SNAPSHOT_STACK_MAX - 1; + for (int i = 0; i < MAX - 1; i++) + snapshots[i] = snapshots[i + 1]; + top = MAX - 1; } - stack->snapshots[stack->top++] = *snapshot; -} + snapshots[top++] = snapshot; + } -static Snapshot* _snapshot_stack_pop(SnapshotStack* stack) -{ - if (stack->top == 0) return nullptr; - return &stack->snapshots[--stack->top]; -} + Snapshot* SnapshotStack::pop() + { + if (is_empty()) return nullptr; + return &snapshots[--top]; + } -static void _snapshot_set(Snapshots* self, Snapshot* snapshot) -{ - if (!snapshot) return; + void SnapshotStack::clear() { top = 0; } - *self->anm2 = snapshot->anm2; - *self->reference = snapshot->reference; - self->preview->time = snapshot->time; - self->action = snapshot->action; + void Snapshots::push(const Snapshot& snapshot) + { + undoStack.push(snapshot); + redoStack.clear(); + } - anm2_spritesheet_texture_pixels_upload(self->anm2); -} - -Snapshot snapshot_get(Snapshots* self) -{ - Snapshot snapshot = {*self->anm2, *self->reference, self->preview->time, self->action}; - anm2_spritesheet_texture_pixels_download(&snapshot.anm2); - return snapshot; -} - -void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview) -{ - self->anm2 = anm2; - self->reference = reference; - self->preview = preview; -} - -void snapshots_reset(Snapshots* self) -{ - self->undoStack = SnapshotStack{}; - self->redoStack = SnapshotStack{}; - self->action.clear(); -} - -void snapshots_undo_push(Snapshots* self, Snapshot* snapshot) -{ - self->redoStack.top = 0; - _snapshot_stack_push(&self->undoStack, snapshot); -} - -void snapshots_undo(Snapshots* self) -{ - if (Snapshot* snapshot = _snapshot_stack_pop(&self->undoStack)) + void Snapshots::undo() + { + if (auto snapshot = undoStack.pop()) { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->redoStack, ¤t); - _snapshot_set(self, snapshot); + redoStack.push(current); + current = *snapshot; } -} + } -void snapshots_redo(Snapshots* self) -{ - if (Snapshot* snapshot = _snapshot_stack_pop(&self->redoStack)) + void Snapshots::redo() + { + if (auto snapshot = redoStack.pop()) { - Snapshot current = snapshot_get(self); - _snapshot_stack_push(&self->undoStack, ¤t); - _snapshot_set(self, snapshot); + undoStack.push(current); + current = *snapshot; } -} \ No newline at end of file + } + + void Snapshots::reset() + { + undoStack.clear(); + redoStack.clear(); + } +}; diff --git a/src/snapshots.h b/src/snapshots.h index 3399a9d..ee7382d 100644 --- a/src/snapshots.h +++ b/src/snapshots.h @@ -1,41 +1,58 @@ #pragma once -#include "anm2.h" -#include "preview.h" -#include "texture.h" +#include "anm2/anm2.h" +#include "playback.h" +#include "storage.h" -#define SNAPSHOT_STACK_MAX 100 -#define SNAPSHOT_ACTION "Action" - -struct Snapshot +namespace anm2ed::snapshots { - Anm2 anm2; - Anm2Reference reference; - f32 time = 0.0f; - std::string action = SNAPSHOT_ACTION; + constexpr auto ACTION = "Action"; + constexpr auto MAX = 100; }; -struct SnapshotStack +namespace anm2ed { - Snapshot snapshots[SNAPSHOT_STACK_MAX]; - s32 top = 0; + class Snapshot + { + public: + anm2::Anm2 anm2{}; + anm2::Reference reference{}; + Playback playback{}; + Storage animation{}; + Storage merge{}; + Storage event{}; + Storage layer{}; + Storage null{}; + Storage sound{}; + Storage spritesheet{}; + Storage items{}; + std::map frames{}; + std::string message = snapshots::ACTION; + }; - bool is_empty() const { return top == 0; } -}; + class SnapshotStack + { + public: + Snapshot snapshots[snapshots::MAX]; + int top{}; -struct Snapshots -{ - Anm2* anm2 = nullptr; - Preview* preview = nullptr; - Anm2Reference* reference = nullptr; - std::string action = SNAPSHOT_ACTION; - SnapshotStack undoStack; - SnapshotStack redoStack; -}; + bool is_empty(); + void push(const Snapshot&); + Snapshot* pop(); + void clear(); + }; -void snapshots_undo_push(Snapshots* self, Snapshot* snapshot); -void snapshots_init(Snapshots* self, Anm2* anm2, Anm2Reference* reference, Preview* preview); -void snapshots_undo(Snapshots* self); -void snapshots_redo(Snapshots* self); -void snapshots_reset(Snapshots* self); -Snapshot snapshot_get(Snapshots* self); \ No newline at end of file + class Snapshots + { + public: + SnapshotStack undoStack{}; + SnapshotStack redoStack{}; + Snapshot current{}; + + Snapshot* get(); + void push(const Snapshot&); + void undo(); + void redo(); + void reset(); + }; +} diff --git a/src/socket.cpp b/src/socket.cpp new file mode 100644 index 0000000..4b408e7 --- /dev/null +++ b/src/socket.cpp @@ -0,0 +1,161 @@ +#include "socket.h" + +namespace anm2ed +{ +#ifdef _WIN32 + namespace + { + struct WSAInitializer + { + WSAInitializer() + { + WSADATA data{}; + WSAStartup(MAKEWORD(2, 2), &data); + } + ~WSAInitializer() { WSACleanup(); } + }; + + WSAInitializer initializer{}; + } +#endif + + Socket::Socket() : handle(SOCKET_INVALID), role(CLIENT) {} + + Socket::Socket(Socket&& other) noexcept : handle(other.handle), role(other.role) { other.handle = SOCKET_INVALID; } + + Socket& Socket::operator=(Socket&& other) noexcept + { + if (this != &other) + { + close(); + handle = other.handle; + role = other.role; + other.handle = SOCKET_INVALID; + } + + return *this; + } + + Socket::~Socket() { close(); } + + bool Socket::open(SocketRole newRole) + { + close(); + role = newRole; + + handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (!is_valid()) return false; + + if (role == SERVER) + { +#ifdef _WIN32 + BOOL opt = TRUE; +#else + int opt = 1; +#endif + ::setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&opt), sizeof(opt)); + } + + return true; + } + + bool Socket::bind(const SocketAddress& address) + { + if (!is_valid()) return false; + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(address.port); + + if (address.host.empty()) + addr.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + if (::inet_pton(AF_INET, address.host.c_str(), &addr.sin_addr) <= 0) return false; + } + + return ::bind(handle, reinterpret_cast(&addr), sizeof(addr)) == 0; + } + + bool Socket::listen() + { + if (!is_valid()) return false; + return ::listen(handle, SOMAXCONN) == 0; + } + + Socket Socket::accept() + { + Socket client{}; + if (!is_valid()) return client; + + auto accepted = ::accept(handle, nullptr, nullptr); + if (accepted == SOCKET_INVALID) return client; + + client.close(); + client.handle = accepted; + client.role = CLIENT; + return client; + } + + bool Socket::connect(const SocketAddress& address) + { + if (!is_valid()) return false; + + sockaddr_in addr{}; + addr.sin_family = AF_INET; + addr.sin_port = htons(address.port); + + if (::inet_pton(AF_INET, address.host.c_str(), &addr.sin_addr) <= 0) return false; + + return ::connect(handle, reinterpret_cast(&addr), sizeof(addr)) == 0; + } + + bool Socket::send(const void* data, size_t size) + { + if (!is_valid() || !data || size == 0) return false; + + auto bytes = reinterpret_cast(data); + size_t totalSent = 0; + + while (totalSent < size) + { + auto sent = ::send(handle, bytes + totalSent, static_cast(size - totalSent), 0); + if (sent <= 0) return false; + totalSent += static_cast(sent); + } + + return true; + } + + bool Socket::receive(void* buffer, size_t size) + { + if (!is_valid() || !buffer || size == 0) return false; + + auto* bytes = reinterpret_cast(buffer); + size_t totalReceived = 0; + + while (totalReceived < size) + { + auto received = ::recv(handle, bytes + totalReceived, static_cast(size - totalReceived), 0); + if (received <= 0) return false; + totalReceived += static_cast(received); + } + + return true; + } + + void Socket::close() + { + if (!is_valid()) return; + +#ifdef _WIN32 + ::closesocket(handle); +#else + ::close(handle); +#endif + handle = SOCKET_INVALID; + } + + bool Socket::is_valid() const { return handle != SOCKET_INVALID; } +} diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..ee8e4ea --- /dev/null +++ b/src/socket.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +#ifdef _WIN32 + #include + #include +using socket_handle = SOCKET; +constexpr socket_handle SOCKET_INVALID = INVALID_SOCKET; +#else + #include + #include + #include + #include +using socket_handle = int; +constexpr socket_handle SOCKET_INVALID = -1; +#endif + +namespace anm2ed +{ + enum SocketRole + { + SERVER, + CLIENT + }; + + struct SocketAddress + { + std::string host{}; + unsigned short port{}; + }; + + class Socket + { + private: + socket_handle handle; + SocketRole role{}; + + public: + Socket(); + ~Socket(); + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; + Socket(Socket&& other) noexcept; + Socket& operator=(Socket&& other) noexcept; + + bool open(SocketRole role); + bool bind(const SocketAddress&); + bool listen(); + Socket accept(); + bool connect(const SocketAddress&); + + bool send(const void*, size_t); + bool receive(void*, size_t); + + void close(); + bool is_valid() const; + }; +} diff --git a/src/state.cpp b/src/state.cpp index 18ad7df..545b835 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1,228 +1,123 @@ #include "state.h" -static void _tick(State* self) +#include +#include + +#include "filesystem_.h" +#include "toast.h" + +using namespace anm2ed::imgui; +using namespace anm2ed::util; +using namespace anm2ed::types; + +namespace anm2ed { - preview_tick(&self->preview); -} + constexpr auto TICK_RATE = 30; + constexpr auto TICK_INTERVAL = (1000 / TICK_RATE); + constexpr auto UPDATE_RATE = 120; + constexpr auto UPDATE_INTERVAL = (1000 / UPDATE_RATE); -static void _update(State* self) -{ - SDL_GetWindowSize(self->window, &self->settings.windowSize.x, &self->settings.windowSize.y); - - imgui_update(&self->imgui); + State::State(SDL_Window*& window, std::vector& arguments) + { + dialog = Dialog(window); - if (self->imgui.isQuit) - self->isRunning = false; -} + for (auto argument : arguments) + manager.open(argument); + } -static void _draw(State* self) -{ - imgui_draw(); + void State::tick(Settings& settings) + { - SDL_GL_SwapWindow(self->window); -} - -bool sdl_init(State* self, bool isTestMode = false) -{ - if (!SDL_Init(SDL_INIT_VIDEO)) - { - log_error(std::format(STATE_SDL_INIT_ERROR, SDL_GetError())); - quit(self); - return false; - } - - if (!isTestMode) log_info(STATE_SDL_INIT_INFO); - - // Todo, when sdl3 mixer is released officially - /* - if ((Mix_Init(STATE_MIX_FLAGS) & mixFlags) != mixFlags) - log_warning(std::format(STATE_MIX_INIT_WARNING, Mix_GetError())); - - if - ( - Mix_OpenAudioDevice - ( - STATE_MIX_SAMPLE_RATE, - STATE_MIX_FORMAT, - STATE_MIX_CHANNELS, - STATE_CHUNK_SIZE, - STATE_MIX_DEVICE, - STATE_MIX_ALLOWED_CHANGES - ) - < 0 - ) - { - log_warning(std::format(STATE_MIX_INIT_WARNING, Mix_GetError())); - Mix_Quit(); + if (auto document = manager.get()) + { + if (auto animation = document->animation_get()) + if (document->playback.isPlaying) + document->playback.tick(document->anm2.info.fps, animation->frameNum, + (animation->isLoop || settings.playbackIsLoop) && !manager.isRecording); } - else - log_info(STATE_MIX_INIT_INFO); - */ + dockspace.tick(manager, settings); + } - if (isTestMode) - { - self->window = SDL_CreateWindow - ( - WINDOW_TITLE, - WINDOW_TEST_MODE_SIZE.x, WINDOW_TEST_MODE_SIZE.y, - WINDOW_TEST_MODE_FLAGS - ); - } - else - { - ivec2 windowSize = self->settings.windowSize; + void State::update(SDL_Window*& window, Settings& settings) + { + SDL_Event event{}; - // Fix for auto-fullscreen on Windows - if (SDL_DisplayID* displayIDs = SDL_GetDisplays(nullptr)) - if (displayIDs[0]) - if (const SDL_DisplayMode* displayMode = SDL_GetDesktopDisplayMode(displayIDs[0])) - if (windowSize.x == displayMode->w && windowSize.y == displayMode->h) - windowSize -= ivec2(1, 1); - - self->window = SDL_CreateWindow - ( - WINDOW_TITLE, - windowSize.x, - windowSize.y, - WINDOW_FLAGS - ); - } + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + switch (event.type) + { + case SDL_EVENT_DROP_FILE: + { + auto droppedFile = event.drop.data; + if (filesystem::path_is_extension(droppedFile, "anm2")) + { + manager.open(std::string(droppedFile)); + SDL_FlashWindow(window, SDL_FLASH_UNTIL_FOCUSED); + } + else if (filesystem::path_is_extension(droppedFile, "png")) + { + if (auto document = manager.get()) + document->spritesheet_add(droppedFile); + else + toasts.info("Failed to add spritesheet! Open a document first."); + } + break; + } + case SDL_EVENT_QUIT: + isQuitting = true; + break; + default: + break; + } + } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, STATE_GL_VERSION_MAJOR); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, STATE_GL_VERSION_MINOR); + ImGui_ImplSDL3_NewFrame(); + ImGui_ImplOpenGL3_NewFrame(); + ImGui::NewFrame(); - self->glContext = SDL_GL_CreateContext(self->window); - - if (!self->glContext) - { - log_error(std::format(STATE_GL_CONTEXT_INIT_ERROR, SDL_GetError())); - quit(self); - return false; - } + taskbar.update(manager, settings, resources, dialog, isQuitting); + documents.update(taskbar, manager, settings, resources, isQuitting); + dockspace.update(taskbar, documents, manager, settings, resources, dialog, clipboard); + toasts.update(); - if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) - { - log_error(std::format(STATE_GLAD_INIT_ERROR)); - quit(self); - return false; - } + ImGui::GetStyle().FontScaleMain = settings.uiScale; + ImGui::GetIO().KeyRepeatDelay = settings.keyboardRepeatDelay; + ImGui::GetIO().KeyRepeatRate = settings.keyboardRepeatRate; + SDL_GetWindowSize(window, &settings.windowSize.x, &settings.windowSize.y); - if (!isTestMode) log_info(std::format(STATE_GL_CONTEXT_INIT_INFO, (const char*)glGetString(GL_VERSION))); - - window_vsync_set(self->settings.isVsync); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glLineWidth(STATE_GL_LINE_WIDTH); - glDisable(GL_MULTISAMPLE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LINE_SMOOTH); + if (isQuitting && manager.documents.empty()) isQuit = true; + } - return true; + void State::render(SDL_Window*& window, Settings& settings) + { + glViewport(0, 0, settings.windowSize.x, settings.windowSize.y); + glClear(GL_COLOR_BUFFER_BIT); + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + SDL_GL_SwapWindow(window); + SDL_GL_SetSwapInterval(settings.isVsync); + } + + void State::loop(SDL_Window*& window, Settings& settings) + { + auto currentTick = SDL_GetTicks(); + auto currentUpdate = SDL_GetTicks(); + + if (currentTick - previousTick >= TICK_INTERVAL) + { + tick(settings); + previousTick = currentTick; + } + + if (currentUpdate - previousUpdate >= UPDATE_INTERVAL) + { + update(window, settings); + render(window, settings); + previousUpdate = currentUpdate; + } + + SDL_Delay(1); + } } - -void init(State* self) -{ - log_info(STATE_INIT_INFO); - - settings_init(&self->settings); - - if (!sdl_init(self)) return; - - if (!self->argument.empty()) - { - anm2_deserialize(&self->anm2, self->argument); - window_title_from_path_set(self->window, self->argument); - } - else - anm2_new(&self->anm2); - - resources_init(&self->resources); - dialog_init(&self->dialog, self->window); - clipboard_init(&self->clipboard, &self->anm2); - preview_init(&self->preview, &self->anm2, &self->reference, &self->resources, &self->settings); - generate_preview_init(&self->generatePreview, &self->anm2, &self->reference, &self->resources, &self->settings); - editor_init(&self->editor, &self->anm2, &self->reference, &self->resources, &self->settings); - snapshots_init(&self->snapshots, &self->anm2, &self->reference, &self->preview); - - imgui_init - ( - &self->imgui, - &self->dialog, - &self->resources, - &self->anm2, - &self->reference, - &self->editor, - &self->preview, - &self->generatePreview, - &self->settings, - &self->snapshots, - &self->clipboard, - self->window, - &self->glContext - ); -} - -void loop(State* self) -{ - self->tick = SDL_GetTicks(); - self->update = self->tick; - - while (self->tick > self->lastTick + TICK_DELAY) - { - self->tick = SDL_GetTicks(); - - if (self->tick - self->lastTick < TICK_DELAY) - SDL_Delay(TICK_DELAY - (self->tick - self->lastTick)); - - _tick(self); - - self->lastTick = self->tick; - } - - if (self->settings.isVsync) - { - _update(self); - _draw(self); - } - else - { - while (self->update > self->lastUpdate + UPDATE_DELAY) - { - self->update = SDL_GetTicks(); - - if (self->update - self->lastUpdate < UPDATE_DELAY) - SDL_Delay(UPDATE_DELAY - (self->update - self->lastUpdate)); - - _update(self); - _draw(self); - - self->lastUpdate = self->update; - } - - SDL_Delay(STATE_DELAY_MIN); - } -} - -void quit(State* self) -{ - imgui_free(); - generate_preview_free(&self->generatePreview); - preview_free(&self->preview); - editor_free(&self->editor); - resources_free(&self->resources); - - /* - Mix_CloseAudio(); - Mix_Quit(); - */ - - SDL_GL_DestroyContext(self->glContext); - SDL_Quit(); - - settings_save(&self->settings); - log_info(STATE_QUIT_INFO); - log_free(); -} \ No newline at end of file diff --git a/src/state.h b/src/state.h index 79fbe9c..07cc3f0 100644 --- a/src/state.h +++ b/src/state.h @@ -1,57 +1,34 @@ #pragma once -#include "imgui.h" +#include -#define STATE_INIT_INFO "Initializing anm2ed (Version 1.1)" -#define STATE_SDL_INIT_ERROR "Failed to initialize SDL! {}" -#define STATE_SDL_INIT_INFO "Initialized SDL" -#define STATE_MIX_INIT_WARNING "Unable to initialize SDL_mixer! {}" -#define STATE_MIX_AUDIO_DEVICE_INIT_WARNING "Unable to initialize audio device! {}" -#define STATE_MIX_INIT_INFO "Initialized SDL_mixer" -#define STATE_GL_CONTEXT_INIT_ERROR "Failed to initialize OpenGL context! {}" -#define STATE_GLAD_INIT_ERROR "Failed to initialize GLAD!" -#define STATE_GL_CONTEXT_INIT_INFO "Initialized OpenGL context (OpenGL {})" -#define STATE_QUIT_INFO "Exiting..." -#define STATE_GL_LINE_WIDTH 2.0f +#include "dockspace.h" -#define STATE_DELAY_MIN 1 - -#define STATE_MIX_FLAGS (MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_WAV) -#define STATE_MIX_SAMPLE_RATE 44100 -#define STATE_MIX_FORMAT MIX_DEFAULT_FORMAT -#define STATE_MIX_CHANNELS 2 -#define STATE_MIX_CHUNK_SIZE 1024 -#define STATE_MIX_DEVICE NULL -#define STATE_MIX_ALLOWED_CHANGES SDL_AUDIO_ALLOW_FORMAT_CHANGE - -#define STATE_GL_VERSION_MAJOR 3 -#define STATE_GL_VERSION_MINOR 3 - -struct State +namespace anm2ed { - SDL_Window* window; - SDL_GLContext glContext; - Imgui imgui; - Dialog dialog; - Editor editor; - Preview preview; - GeneratePreview generatePreview; - Anm2 anm2; - Anm2Reference reference; - Resources resources; - Settings settings; - Snapshots snapshots; - Clipboard clipboard; - std::string argument{}; - std::string lastAction{}; - u64 lastTick{}; - u64 tick{}; - u64 update{}; - u64 lastUpdate{}; - bool isRunning = true; -}; + class State + { + void tick(Settings&); + void update(SDL_Window*&, Settings&); + void render(SDL_Window*&, Settings&); -bool sdl_init(State* self, bool isTestMode); -void init(State* state); -void loop(State* state); -void quit(State* state); \ No newline at end of file + public: + bool isQuit{}; + bool isQuitting{}; + Manager manager; + Resources resources; + Dialog dialog; + Clipboard clipboard; + + imgui::Taskbar taskbar; + imgui::Documents documents; + imgui::Dockspace dockspace; + + uint64_t previousTick{}; + uint64_t previousUpdate{}; + + State(SDL_Window*&, std::vector&); + + void loop(SDL_Window*&, Settings&); + }; +}; diff --git a/src/storage.cpp b/src/storage.cpp new file mode 100644 index 0000000..95b9e79 --- /dev/null +++ b/src/storage.cpp @@ -0,0 +1,12 @@ +#include "storage.h" + +namespace anm2ed +{ + void Storage::labels_set(std::vector labels) + { + labelsString = labels; + this->labels.clear(); + for (auto& label : labelsString) + this->labels.emplace_back(label.c_str()); + } +} \ No newline at end of file diff --git a/src/storage.h b/src/storage.h new file mode 100644 index 0000000..db43cf3 --- /dev/null +++ b/src/storage.h @@ -0,0 +1,28 @@ +#pragma once + +#include "anm2/anm2.h" +#include "imgui_.h" + +namespace anm2ed +{ + class Storage + { + public: + int reference{-1}; + int hovered{-1}; + std::set unused{}; + std::vector labelsString{}; + std::vector labels{}; + imgui::MultiSelectStorage selection{}; + + void labels_set(std::vector); + }; + + class FrameStorage + { + public: + anm2::Type referenceType{anm2::NONE}; + int referenceID{-1}; + int referenceFrameIndex{-1}; + }; +} \ No newline at end of file diff --git a/src/texture.cpp b/src/texture.cpp deleted file mode 100644 index 8b80bb2..0000000 --- a/src/texture.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#if defined(__clang__) || defined(__GNUC__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - #pragma GCC diagnostic ignored "-Wunused-function" - #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - -#include "texture.h" - -#define STBI_ONLY_PNG -#define STBI_NO_FAILURE_STRINGS -#define STBI_NO_HDR -#define STB_IMAGE_IMPLEMENTATION -#include -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include - -static void _texture_gl_set(Texture* self, const u8* data) -{ - if (self->id == GL_ID_NONE) glGenTextures(1, &self->id); - - glBindTexture(GL_TEXTURE_2D, self->id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); -} - -std::vector texture_download(const Texture* self) -{ - std::vector pixels(self->size.x * self->size.y * TEXTURE_CHANNELS); - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ROW_LENGTH, 0); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); - - return pixels; -} - -bool texture_from_path_init(Texture* self, const std::string& path) -{ - u8* data = stbi_load(path.c_str(), &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); - - if (!data) - { - log_error(std::format(TEXTURE_INIT_ERROR, path)); - return false; - } - - self->isInvalid = false; - - log_info(std::format(TEXTURE_INIT_INFO, path)); - - _texture_gl_set(self, data); - - return true; -} - -bool texture_from_encoded_data_init(Texture* self, ivec2 size, const u8* data, u32 length) -{ - *self = Texture{}; - self->size = size; - - u8* textureData = stbi_load_from_memory(data, length, &self->size.x, &self->size.y, nullptr, TEXTURE_CHANNELS); - - if (!textureData) - { - self->isInvalid = true; - return false; - } - - _texture_gl_set(self, textureData); - - return true; -} - -bool texture_from_rgba_init(Texture* self, ivec2 size, const u8* data) -{ - *self = Texture{}; - self->size = size; - self->isInvalid = false; - - _texture_gl_set(self, data); - - return true; -} - -bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size) -{ - bool isSuccess = stbi_write_png(path.c_str(), size.x, size.y, TEXTURE_CHANNELS, data, size.x * TEXTURE_CHANNELS); - if (!isSuccess) log_error(std::format(TEXTURE_SAVE_ERROR, path)); - else log_info(std::format(TEXTURE_SAVE_INFO, path)); - - return isSuccess; -} - -bool texture_from_gl_write(Texture* self, const std::string& path) -{ - return texture_from_rgba_write(path, texture_download(self).data(), self->size); -} - -void texture_free(Texture* self) -{ - if (self->isInvalid) return; - - glDeleteTextures(1, &self->id); - *self = Texture{}; -} - -bool texture_pixel_set(Texture* self, ivec2 position, vec4 color) -{ - if - ( - position.x < 0 || position.y < 0 || - position.x >= self->size.x || position.y >= self->size.y - ) - return false; - - uint8_t rgba8[4] = {FLOAT_TO_U8(color.r), FLOAT_TO_U8(color.g), FLOAT_TO_U8(color.b), FLOAT_TO_U8(color.a)}; - - glBindTexture(GL_TEXTURE_2D, self->id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexSubImage2D(GL_TEXTURE_2D, 0,position.x, position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba8); - - return true; -} diff --git a/src/texture.h b/src/texture.h deleted file mode 100644 index 3c55c1a..0000000 --- a/src/texture.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "log.h" - -#define TEXTURE_CHANNELS 4 -#define TEXTURE_INIT_INFO "Initialized texture from file: {}" -#define TEXTURE_INIT_ERROR "Failed to initialize texture from file: {}" -#define TEXTURE_SAVE_INFO "Saved texture to: {}" -#define TEXTURE_SAVE_ERROR "Failed to save texture to: {}" - -struct Texture -{ - GLuint id = GL_ID_NONE; - ivec2 size{}; - bool isInvalid = true; - - auto operator<=>(const Texture&) const = default; -}; - -bool texture_from_encoded_data_init(Texture* self, ivec2 size, const u8* data, u32 length); -bool texture_from_gl_write(Texture* self, const std::string& path); -bool texture_from_path_init(Texture* self, const std::string& path); -bool texture_from_rgba_init(Texture* self, ivec2 size, const u8* data); -bool texture_from_rgba_write(const std::string& path, const u8* data, ivec2 size); -bool texture_pixel_set(Texture* self, ivec2 position, vec4 color); -void texture_free(Texture* self); -std::vector texture_download(const Texture* self); \ No newline at end of file diff --git a/src/tool.h b/src/tool.h index 132e806..109630e 100644 --- a/src/tool.h +++ b/src/tool.h @@ -1,37 +1,81 @@ #pragma once -#include "COMMON.h" +#include "icon.h" +#include "settings.h" -#define TOOL_STEP 1 -#define TOOL_STEP_MOD 10 - -enum ToolType +namespace anm2ed::tool { - TOOL_PAN, - TOOL_MOVE, - TOOL_ROTATE, - TOOL_SCALE, - TOOL_CROP, - TOOL_DRAW, - TOOL_ERASE, - TOOL_COLOR_PICKER, - TOOL_UNDO, - TOOL_REDO, - TOOL_COLOR, - TOOL_COUNT, -}; + enum Type + { + PAN, + MOVE, + ROTATE, + SCALE, + CROP, + DRAW, + ERASE, + COLOR_PICKER, + UNDO, + REDO, + COLOR, + COUNT + }; -const SDL_SystemCursor CURSOR_DEFAULT = SDL_SYSTEM_CURSOR_DEFAULT; -const SDL_SystemCursor TOOL_CURSORS[TOOL_COUNT] = -{ - SDL_SYSTEM_CURSOR_POINTER, - SDL_SYSTEM_CURSOR_MOVE, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_NE_RESIZE, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_CROSSHAIR, - SDL_SYSTEM_CURSOR_DEFAULT, - SDL_SYSTEM_CURSOR_DEFAULT -}; \ No newline at end of file + enum AreaType + { + ANIMATION_PREVIEW, + SPRITESHEET_EDITOR, + ALL + }; + + struct Info + { + ImGuiMouseCursor cursor{ImGuiMouseCursor_None}; + resource::icon::Type icon{}; + ShortcutType shortcut{}; + AreaType areaType; + const char* label{}; + const char* tooltip{}; + }; + + constexpr Info INFO[] = { + {ImGuiMouseCursor_Hand, resource::icon::PAN, SHORTCUT_PAN, ALL, "##Pan", + "Use the pan tool.\nWill shift the view as the cursor is dragged.\nYou can also use the middle mouse button to " + "pan at any time."}, + + {ImGuiMouseCursor_ResizeAll, resource::icon::MOVE, SHORTCUT_MOVE, ALL, "##Move", + "Use the move tool.\nAnimation Preview: Will move the position of the frame." + "\nSpritesheet Editor: Will move the pivot, and holding right click will use the Crop functionality instead." + "\nUse mouse or directional keys to change the value."}, + + {ImGuiMouseCursor_Arrow, resource::icon::ROTATE, SHORTCUT_ROTATE, ANIMATION_PREVIEW, "##Rotate", + "Use the rotate tool.\nWill rotate the selected item as the cursor is dragged, or directional keys are " + "pressed.\n(Animation Preview only.)"}, + + {ImGuiMouseCursor_ResizeNESW, resource::icon::SCALE, SHORTCUT_SCALE, ANIMATION_PREVIEW, "##Scale", + "Use the scale tool.\nWill scale the selected item as the cursor is dragged, or directional keys are " + "pressed.\n(Animation Preview only.)"}, + + {ImGuiMouseCursor_Arrow, resource::icon::CROP, SHORTCUT_CROP, SPRITESHEET_EDITOR, "##Crop", + "Use the crop tool.\nWill produce a crop rectangle based on how the cursor is dragged, or directional keys are " + "pressed.\nHold CTRL with arrow keys to change position." + "\nHolding right click will use the Move tool's functionality." + "\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Arrow, resource::icon::DRAW, SHORTCUT_DRAW, SPRITESHEET_EDITOR, "##Draw", + "Draws pixels onto the selected spritesheet, with the current color.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Arrow, resource::icon::ERASE, SHORTCUT_ERASE, SPRITESHEET_EDITOR, "##Erase", + "Erases pixels from the selected spritesheet.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_Arrow, resource::icon::COLOR_PICKER, SHORTCUT_COLOR_PICKER, SPRITESHEET_EDITOR, + "##Color Picker", "Selects a color from the canvas.\n(Spritesheet Editor only.)"}, + + {ImGuiMouseCursor_None, resource::icon::UNDO, SHORTCUT_UNDO, ALL, "##Undo", "Undoes the last action."}, + + {ImGuiMouseCursor_None, resource::icon::REDO, SHORTCUT_REDO, ALL, "##Redo", "Redoes the last action."}, + + {ImGuiMouseCursor_None, resource::icon::NONE, SHORTCUT_COLOR, ALL, "##Color", + "Selects the color to be used for drawing.\n(Spritesheet Editor only.)"}, + }; +} \ No newline at end of file diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..80b58e7 --- /dev/null +++ b/src/types.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include + +namespace anm2ed::types::draw_order +{ + enum Type + { + BELOW, + ABOVE + }; +} + +namespace anm2ed::types::shortcut +{ + enum Type + { + FOCUSED, + GLOBAL, + FOCUSED_SET, + GLOBAL_SET + }; +} + +namespace anm2ed::types::locale +{ + enum Type + { + LOCAL, + GLOBAL + }; +} + +namespace anm2ed::types::source +{ + enum Type + { + NEW, + EXISTING + }; +} + +namespace anm2ed::types::merge +{ + enum Type + { + PREPEND, + APPEND, + REPLACE, + IGNORE + }; +} + +namespace anm2ed::types::color +{ + using namespace glm; + + constexpr auto WHITE = vec4(1.0); + constexpr auto BLACK = vec4(0.0, 0.0, 0.0, 1.0); + constexpr auto RED = vec4(1.0, 0.0, 0.0, 1.0); + constexpr auto GREEN = vec4(0.0, 1.0, 0.0, 1.0); + constexpr auto BLUE = vec4(0.0, 0.0, 1.0, 1.0); + constexpr auto PINK = vec4(1.0, 0.0, 1.0, 1.0); + constexpr auto TRANSPARENT = vec4(); +} + +namespace anm2ed::types +{ + constexpr auto ID_NONE = -1; + + constexpr ImVec2 to_imvec2(const glm::vec2& v) noexcept + { + return {v.x, v.y}; + } + constexpr glm::vec2 to_vec2(const ImVec2& v) noexcept + { + return {v.x, v.y}; + } + + constexpr glm::ivec2 to_ivec2(const ImVec2& v) noexcept + { + return {v.x, v.y}; + } + + constexpr ImVec4 to_imvec4(const glm::vec4& v) noexcept + { + return {v.x, v.y, v.z, v.w}; + } + + constexpr glm::vec4 to_vec4(const ImVec4& v) noexcept + { + return {v.x, v.y, v.z, v.w}; + } + + template constexpr T& dummy_value() + { + static T value{}; + return value; + } +} \ No newline at end of file diff --git a/src/util/filesystem_.cpp b/src/util/filesystem_.cpp new file mode 100644 index 0000000..251df42 --- /dev/null +++ b/src/util/filesystem_.cpp @@ -0,0 +1,76 @@ +#include "filesystem_.h" + +#include +#include +#include + +#include "string_.h" + +namespace anm2ed::util::filesystem +{ + std::string path_pref_get(const char* org, const char* app) + { + auto path = SDL_GetPrefPath(org, app); + std::string string = path; + SDL_free(path); + return string; + } + + std::string path_preferences_get() { return path_pref_get(nullptr, "anm2ed"); } + std::string path_base_get() { return std::string(SDL_GetBasePath()); } + std::string path_executable_get() { return std::filesystem::path(path_base_get()) / "anm2ed"; } + +#ifdef __unix__ + std::string path_application_get() + { + return std::filesystem::path(path_pref_get(nullptr, "applications")) / "anm2ed.desktop"; + } + + std::string path_mime_get() + { + return std::filesystem::path(path_pref_get(nullptr, "mime/application")) / "x-anm2+xml.xml"; + } + + std::string path_icon_get() { return std::filesystem::path(path_preferences_get()) / "anm2ed.png"; } + std::string path_icon_file_get() + { + return std::filesystem::path(path_preferences_get()) / "application-x-anm2+xml.png"; + } + +#endif + + bool path_is_exist(const std::string& path) + { + std::error_code errorCode; + return std::filesystem::exists(path, errorCode) && ((void)std::filesystem::status(path, errorCode), !errorCode); + } + + bool path_is_extension(const std::string& path, const std::string& extension) + { + auto e = std::filesystem::path(path).extension().string(); + std::transform(e.begin(), e.end(), e.begin(), ::tolower); + return e == ("." + extension); + } + + std::filesystem::path path_lower_case_backslash_handle(std::filesystem::path& path) + { + if (path_is_exist(path)) return path; + if (path_is_exist(string::backslash_replace(path))) return path; + return string::to_lower(path); + } + + WorkingDirectory::WorkingDirectory(const std::string& path, bool isFile) + { + previous = std::filesystem::current_path(); + if (isFile) + { + std::filesystem::path filePath = path; + std::filesystem::path parentPath = filePath.parent_path(); + std::filesystem::current_path(parentPath); + } + else + std::filesystem::current_path(path); + } + + WorkingDirectory::~WorkingDirectory() { std::filesystem::current_path(previous); } +} \ No newline at end of file diff --git a/src/util/filesystem_.h b/src/util/filesystem_.h new file mode 100644 index 0000000..f9bf2e7 --- /dev/null +++ b/src/util/filesystem_.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace anm2ed::util::filesystem +{ +#ifdef __unix__ + std::string path_application_get(); + std::string path_mime_get(); + std::string path_icon_get(); + std::string path_icon_file_get(); +#endif + + std::string path_pref_get(); + std::string path_preferences_get(); + std::string path_base_get(); + std::string path_executable_get(); + + bool path_is_exist(const std::string&); + bool path_is_extension(const std::string&, const std::string&); + + std::filesystem::path path_lower_case_backslash_handle(std::filesystem::path&); + + class WorkingDirectory + { + public: + std::filesystem::path previous; + + WorkingDirectory(const std::string&, bool = false); + ~WorkingDirectory(); + }; +} diff --git a/src/util/map_.h b/src/util/map_.h new file mode 100644 index 0000000..6a75c89 --- /dev/null +++ b/src/util/map_.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace anm2ed::util::map +{ + template int next_id_get(std::map& map) + { + int id = 0; + + for (auto& [key, value] : map) + { + if (key != id) break; + ++id; + } + + return id; + } + + template T1* find(std::map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} diff --git a/src/util/math_.cpp b/src/util/math_.cpp new file mode 100644 index 0000000..a34b62a --- /dev/null +++ b/src/util/math_.cpp @@ -0,0 +1,81 @@ +#include "math.h" + +#include +#include + +using namespace glm; + +namespace anm2ed::util::math +{ + constexpr auto FLOAT_FORMAT_MAX_DECIMALS = 7; + constexpr auto FLOAT_FORMAT_EPSILON = 1e-7f; + constexpr float FLOAT_FORMAT_POW10[] = {1.f, 10.f, 100.f, 1000.f, 10000.f, 100000.f, 1000000.f, 10000000.f}; + + float round_nearest_multiple(float value, float multiple) + { + return (roundf((value) / (multiple)) * (multiple)); + } + + int float_decimals_needed(float value) + { + for (int decimalCount = 0; decimalCount <= FLOAT_FORMAT_MAX_DECIMALS; ++decimalCount) + { + auto scale = FLOAT_FORMAT_POW10[decimalCount]; + auto rounded = roundf(value * scale) / scale; + if (fabsf(value - rounded) < FLOAT_FORMAT_EPSILON) return decimalCount; + } + return FLOAT_FORMAT_MAX_DECIMALS; + } + + const char* float_format_get(float value) + { + static std::string formatString{}; + int decimalCount = float_decimals_needed(value); + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); + } + + const char* vec2_format_get(vec2& value) + { + static std::string formatString{}; + int decimalCountX = float_decimals_needed(value.x); + int decimalCountY = float_decimals_needed(value.y); + int decimalCount = (decimalCountX > decimalCountY) ? decimalCountX : decimalCountY; + formatString = (decimalCount == 0) ? "%.0f" : ("%." + std::to_string(decimalCount) + "f"); + return formatString.c_str(); + } + + mat4 quad_model_get(vec2 size, vec2 position, vec2 pivot, vec2 scale, float rotation) + { + vec2 scaleAbsolute = glm::abs(scale); + vec2 scaleSign = glm::sign(scale); + vec2 pivotScaled = pivot * scaleAbsolute; + vec2 sizeScaled = size * scaleAbsolute; + + mat4 model(1.0f); + model = glm::translate(model, vec3(position - pivotScaled, 0.0f)); + model = glm::translate(model, vec3(pivotScaled, 0.0f)); + model = glm::scale(model, vec3(scaleSign, 1.0f)); + model = glm::rotate(model, glm::radians(rotation), vec3(0, 0, 1)); + model = glm::translate(model, vec3(-pivotScaled, 0.0f)); + model = glm::scale(model, vec3(sizeScaled, 1.0f)); + return model; + } + + mat4 quad_model_parent_get(vec2 position, vec2 pivot, vec2 scale, float rotation) + { + vec2 scaleSign = glm::sign(scale); + vec2 scaleAbsolute = glm::abs(scale); + float handedness = (scaleSign.x * scaleSign.y) < 0.0f ? -1.0f : 1.0f; + + mat4 local(1.0f); + local = glm::translate(local, vec3(pivot, 0.0f)); + local = glm::scale(local, vec3(scaleSign, 1.0f)); + local = glm::rotate(local, glm::radians(rotation) * handedness, vec3(0, 0, 1)); + local = glm::translate(local, vec3(-pivot, 0.0f)); + local = glm::scale(local, vec3(scaleAbsolute, 1.0f)); + + return glm::translate(mat4(1.0f), vec3(position, 0.0f)) * local; + } + +} \ No newline at end of file diff --git a/src/util/math_.h b/src/util/math_.h new file mode 100644 index 0000000..5a1beac --- /dev/null +++ b/src/util/math_.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +namespace anm2ed::util::math +{ + template constexpr T percent_to_unit(T value) + { + return value / 100.0f; + } + + template constexpr T unit_to_percent(T value) + { + return value * 100.0f; + } + + constexpr float uint8_to_float(int value) + { + return (float)(value / 255.0f); + } + + constexpr int float_to_uint8(float value) + { + return (int)(value * 255); + } + + constexpr std::array uv_vertices_get(glm::vec2 uvMin, glm::vec2 uvMax) + { + return {0.0f, 0.0f, uvMin.x, uvMin.y, 1.0f, 0.0f, uvMax.x, uvMin.y, + 1.0f, 1.0f, uvMax.x, uvMax.y, 0.0f, 1.0f, uvMin.x, uvMax.y}; + } + + float round_nearest_multiple(float, float); + + int float_decimals_needed(float); + + const char* float_format_get(float); + + const char* vec2_format_get(glm::vec2&); + + glm::mat4 quad_model_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = glm::vec2(1.0f), float = {}); + glm::mat4 quad_model_parent_get(glm::vec2 = {}, glm::vec2 = {}, glm::vec2 = glm::vec2(1.0f), float = {}); +} \ No newline at end of file diff --git a/src/util/string_.cpp b/src/util/string_.cpp new file mode 100644 index 0000000..2cef87f --- /dev/null +++ b/src/util/string_.cpp @@ -0,0 +1,31 @@ +#include "string_.h" + +#include + +namespace anm2ed::util::string +{ + std::string to_lower(const std::string& string) + { + std::string transformed = string; + std::ranges::transform(transformed, transformed.begin(), [](const unsigned char c) { return std::tolower(c); }); + return transformed; + } + + std::string backslash_replace(const std::string& string) + { + std::string transformed = string; + for (char& character : transformed) + if (character == '\\') character = '/'; + return transformed; + } + + std::string quote(const std::string& string) + { + return "\"" + string + "\""; + } + + bool to_bool(const std::string& string) + { + return to_lower(string) == "true"; + } +} diff --git a/src/util/string_.h b/src/util/string_.h new file mode 100644 index 0000000..c76668f --- /dev/null +++ b/src/util/string_.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace anm2ed::util::string +{ + std::string to_lower(const std::string&); + std::string backslash_replace(const std::string&); + bool to_bool(const std::string&); +} diff --git a/src/util/time_.cpp b/src/util/time_.cpp new file mode 100644 index 0000000..96021c4 --- /dev/null +++ b/src/util/time_.cpp @@ -0,0 +1,16 @@ +#include "time_.h" + +#include + +namespace anm2ed::util::time +{ + std::string get(const char* format) + { + auto now = std::chrono::system_clock::now(); + auto time = std::chrono::system_clock::to_time_t(now); + auto localTime = *std::localtime(&time); + std::ostringstream timeString; + timeString << std::put_time(&localTime, format); + return timeString.str(); + } +} \ No newline at end of file diff --git a/src/util/time_.h b/src/util/time_.h new file mode 100644 index 0000000..f2f716d --- /dev/null +++ b/src/util/time_.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace anm2ed::util::time +{ + constexpr auto SECOND_M = 60; + + std::string get(const char*); +} \ No newline at end of file diff --git a/src/util/unordered_map_.h b/src/util/unordered_map_.h new file mode 100644 index 0000000..2c37e77 --- /dev/null +++ b/src/util/unordered_map_.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace anm2ed::util::unordered_map +{ + template T1* find(std::unordered_map& map, T0 index) + { + return map.contains(index) ? &map[index] : nullptr; + } +} diff --git a/src/util/vector_.h b/src/util/vector_.h new file mode 100644 index 0000000..eba0dd9 --- /dev/null +++ b/src/util/vector_.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include +#include + +namespace anm2ed::util::vector +{ + template T* find(std::vector& v, int index) + { + return index >= 0 && index < (int)v.size() ? &v[index] : nullptr; + } + + template bool in_bounds(std::vector& v, int index) + { + return index >= 0 && index < (int)v.size(); + } + template void clamp_in_bounds(std::vector& v, int& index) + { + index = std::clamp(index, 0, (int)v.size() - 1); + } + + template std::set move_indices(std::vector& v, std::vector& indices, int index) + { + if (indices.empty()) return {}; + + std::vector sorted = indices; + std::sort(sorted.begin(), sorted.end()); + sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end()); + + // Determine if we are dragging items from below the target (insert before) or above (insert after) + bool insertAfter = !sorted.empty() && sorted.front() <= index; + + std::vector moveItems; + moveItems.reserve(sorted.size()); + for (int i : sorted) + moveItems.push_back(std::move(v[i])); + + for (auto i : sorted | std::views::reverse) + v.erase(v.begin() + i); + + int originalSize = (int)v.size() + (int)sorted.size(); + int reference = insertAfter ? index + 1 : index; + reference = std::clamp(reference, 0, originalSize); + + int removedBeforeReference = 0; + for (int i : sorted) + if (i < reference) ++removedBeforeReference; + + int insertPos = reference - removedBeforeReference; + insertPos = std::clamp(insertPos, 0, (int)v.size()); + + v.insert(v.begin() + insertPos, std::make_move_iterator(moveItems.begin()), + std::make_move_iterator(moveItems.end())); + + std::set moveIndices{}; + for (int i = 0; i < (int)moveItems.size(); i++) + moveIndices.insert(insertPos + i); + + return moveIndices; + } + +} diff --git a/src/util/xml_.cpp b/src/util/xml_.cpp new file mode 100644 index 0000000..47299db --- /dev/null +++ b/src/util/xml_.cpp @@ -0,0 +1,38 @@ +#include "xml_.h" + +#include "math_.h" + +using namespace tinyxml2; + +namespace anm2ed::util::xml +{ + std::string document_to_string(XMLDocument& self) + { + XMLPrinter printer{}; + self.Print(&printer); + return std::string(printer.CStr()); + } + + XMLError query_string_attribute(XMLElement* element, const char* attribute, std::string* out) + { + const char* temp = nullptr; + auto result = element->QueryStringAttribute(attribute, &temp); + if (result == XML_SUCCESS && temp) *out = temp; + return result; + } + + XMLError query_path_attribute(XMLElement* element, const char* attribute, std::filesystem::path* out) + { + std::string temp{}; + auto result = query_string_attribute(element, attribute, &temp); + if (result == XML_SUCCESS) *out = temp; + return result; + } + + void query_color_attribute(XMLElement* element, const char* attribute, float& out) + { + int value{}; + element->QueryIntAttribute(attribute, &value); + out = math::uint8_to_float(value); + } +} \ No newline at end of file diff --git a/src/util/xml_.h b/src/util/xml_.h new file mode 100644 index 0000000..0a4cf2b --- /dev/null +++ b/src/util/xml_.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include + +namespace anm2ed::util::xml +{ + std::string document_to_string(tinyxml2::XMLDocument&); + tinyxml2::XMLError query_string_attribute(tinyxml2::XMLElement*, const char*, std::string*); + tinyxml2::XMLError query_path_attribute(tinyxml2::XMLElement*, const char*, std::filesystem::path*); + void query_color_attribute(tinyxml2::XMLElement*, const char*, float&); +} diff --git a/src/window.cpp b/src/window.cpp deleted file mode 100644 index 553d0f4..0000000 --- a/src/window.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "window.h" - -void window_title_from_path_set(SDL_Window* self, const std::string& path) -{ - if (!path.empty()) - SDL_SetWindowTitle(self, std::format(WINDOW_TITLE_FORMAT, path).c_str()); - else - SDL_SetWindowTitle(self, WINDOW_TITLE); -} - -void window_vsync_set(bool isVsync) -{ - if (isVsync) - SDL_GL_SetSwapInterval(1); - else - SDL_GL_SetSwapInterval(0); -} \ No newline at end of file diff --git a/src/window.h b/src/window.h deleted file mode 100644 index 5cffb22..0000000 --- a/src/window.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "COMMON.h" - -#define WINDOW_TITLE "Anm2Ed" -#define WINDOW_TITLE_FORMAT "Anm2Ed ({})" -#define WINDOW_FLAGS SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL -#define WINDOW_TEST_MODE_FLAGS WINDOW_FLAGS | SDL_WINDOW_HIDDEN - -static const ivec2 WINDOW_TEST_MODE_SIZE = {1, 1}; - -void window_title_from_path_set(SDL_Window* self, const std::string& path); -bool window_color_from_position_get(SDL_Window* self, vec2 position, vec4* color); -void window_vsync_set(bool isVsync); \ No newline at end of file