diff --git a/Kconfig b/Kconfig index ac1b0fb30..64dd2f6d4 100644 --- a/Kconfig +++ b/Kconfig @@ -811,6 +811,9 @@ menu "LVGL configuration" int "Memory used by FreeType to cache characters [bytes] (-1: no caching)" depends on LV_USE_FREETYPE default 16384 + + config LV_USE_RLOTTIE + bool "Lottie library" endmenu menu "Others" diff --git a/docs/libs/index.md b/docs/libs/index.md index 02c9e8e8c..9ef96619e 100644 --- a/docs/libs/index.md +++ b/docs/libs/index.md @@ -17,5 +17,6 @@ gif freetype qrcode + rlottie ``` diff --git a/docs/libs/rlottie.md b/docs/libs/rlottie.md new file mode 100644 index 000000000..fba8ad76a --- /dev/null +++ b/docs/libs/rlottie.md @@ -0,0 +1,86 @@ +```eval_rst +.. include:: /header.rst +:github_url: |github_link_base|/libs/rlottie.md +``` + + +# Lottie player +Allows to use Lottie animations in LVGL. Taken from this [base repository](https://github.com/ValentiWorkLearning/lv_rlottie) + +LVGL provides the interface to [Samsung/rlottie](https://github.com/Samsung/rlottie) library's C API. That is the actual Lottie player is not part of LVGL, it needs to be built separately. + +## Build Rlottie +To build Samsung's Rlottie C++14-compatible compiler and optionally CMake 3.14 or higher is required. + +To build on desktop you can follow the instrutions from Rlottie's [README](https://github.com/Samsung/rlottie/blob/master/README.md). In the most basic case it looks like this: +``` +mkdir rlottie_workdir +cd rlottie_workdir +git clone https://github.com/Samsung/rlottie.git +mkdir build > +cd build +cmake ../rlottie +make -j +make install +``` + +And finally add the `-lrlottie` flag to your linker. + +On embedded systems you need to take care of integrating Rlottie to the given build system. + + +## Usage + +You can use animation from files or raw data (text). In either case first you need to enable `LV_USE_RLOTTIE` in `lv_conf.h`. + + +The `width` and `height` of the object be set in the *create* function and the animation will be scaled accordingly. + +### Use Rlottie from file + +To create a Lottie animation from file use: +```c + lv_obj_t * lottie = lv_rlottie_create_from_file(parent, width, height, "path/to/lottie.json"); +``` + +Note that, Rlottie uses the standard STDIO C file API, so you can use the path "normally" and no LVGL specific driver letter is required. + + +### Use Rlottie from raw string data + +`lv_example_rlottie_approve.c` contains an example animation in raw format. Instead storing the JSON string a hex array is stored for the following reasons: +- avoid escaping `"` in the JSON file +- some compilers don't support very long strings + +`lvgl/scripts/filetohex.py` can be used to convert a Lottie file a hex array. E.g.: +``` +./filetohex.py path/to/lottie.json > out.txt +``` + +To create an animation from raw data: + +```c +extern const uint8_t lottie_data[]; +lv_obj_t* lottie = lv_rlottie_create_from_raw(parent, width, height, (const char *)lottie_data); +``` + +## Getting animations + +Lottie is standard and popular format so you can find many animation files on the web. +For example: https://lottiefiles.com/ + +You can also create your own animations with Adobe After Effects or similar software. + +## Example +```eval_rst + +.. include:: ../../examples/libs/rlottie/index.rst + +``` + +## API + +```eval_rst + +.. doxygenfile:: lv_rlottie.h + :project: lvgl \ No newline at end of file diff --git a/examples/libs/lv_example_libs.h b/examples/libs/lv_example_libs.h index a63524b84..7a1647581 100644 --- a/examples/libs/lv_example_libs.h +++ b/examples/libs/lv_example_libs.h @@ -19,6 +19,7 @@ extern "C" { #include "sjpg/lv_example_sjpg.h" #include "qrcode/lv_example_qrcode.h" #include "freetype/lv_example_freetype.h" +#include "rlottie/lv_example_rlottie.h" /********************* * DEFINES diff --git a/examples/libs/rlottie/index.rst b/examples/libs/rlottie/index.rst new file mode 100644 index 000000000..022f41147 --- /dev/null +++ b/examples/libs/rlottie/index.rst @@ -0,0 +1,12 @@ +Load a Lottie animation from raw data +""""""""""""""""""""""""""""""""""""" + +.. lv_example:: libs/rlottie/lv_example_rlottie_1 + :language: c + +Load a Lottie animation from a file +""""""""""""""""""""""""""""""""""" + +.. lv_example:: libs/rlottie/lv_example_rlottie_2 + :language: c + diff --git a/examples/libs/rlottie/lv_example_rlottie.h b/examples/libs/rlottie/lv_example_rlottie.h new file mode 100644 index 000000000..b45826ebe --- /dev/null +++ b/examples/libs/rlottie/lv_example_rlottie.h @@ -0,0 +1,39 @@ +/** + * @file lv_example_rlottie.h + * + */ + +#ifndef LV_EXAMPLE_RLOTTIE_H +#define LV_EXAMPLE_RLOTTIE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_example_rlottie_1(void); +void lv_example_rlottie_2(void); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_EXAMPLE_SJPG_H*/ diff --git a/examples/libs/rlottie/lv_example_rlottie_1.c b/examples/libs/rlottie/lv_example_rlottie_1.c new file mode 100644 index 000000000..3470841b3 --- /dev/null +++ b/examples/libs/rlottie/lv_example_rlottie_1.c @@ -0,0 +1,14 @@ +#include "../../lv_examples.h" +#if LV_USE_RLOTTIE && LV_BUILD_EXAMPLES + +/** + * Load an lottie animation from flash + */ +void lv_example_rlottie_1(void) +{ + extern const uint8_t lv_example_rlottie_approve[]; + lv_obj_t * lottie = lv_rlottie_create_from_raw(lv_scr_act(), 100, 100, (const void *)lv_example_rlottie_approve); + lv_obj_center(lottie); +} + +#endif diff --git a/examples/libs/rlottie/lv_example_rlottie_2.c b/examples/libs/rlottie/lv_example_rlottie_2.c new file mode 100644 index 000000000..a93291ab9 --- /dev/null +++ b/examples/libs/rlottie/lv_example_rlottie_2.c @@ -0,0 +1,15 @@ +#include "../../lv_examples.h" +#if LV_USE_RLOTTIE && LV_BUILD_EXAMPLES + +/** + * Load an lottie animation from file + */ +void lv_example_rlottie_2(void) +{ + /*The rlottie library uses STDIO file API, so there is no drievr letter for LVGL*/ + lv_obj_t * lottie = lv_rlottie_create_from_file(lv_scr_act(), 100, 100, + "lvgl/examples/libs/rlottie/lv_example_rlottie_approve.json"); + lv_obj_center(lottie); +} + +#endif diff --git a/examples/libs/rlottie/lv_example_rlottie_approve.c b/examples/libs/rlottie/lv_example_rlottie_approve.c new file mode 100644 index 000000000..a0ded8243 --- /dev/null +++ b/examples/libs/rlottie/lv_example_rlottie_approve.c @@ -0,0 +1,30 @@ + +/* The original JSON string is converted to hex array because C99 requires support only 4096 character long strings. + + lvgl/scripts/tohex.py is sued to convert a json file to a hex array. E.g. + ./filetohex.py my_lottie.json > output.txt + + If your compiler support very long strings you can do + const char * my_lottie = "JSON data here"; + But be sure to replace all " characters with \". + + +*/ + +#include "../../../lvgl.h" + +#if LV_BUILD_EXAMPLES && LV_USE_RLOTTIE + +const uint8_t lv_example_rlottie_approve[] = { + 0x7b, 0x22, 0x76, 0x22, 0x3a, 0x22, 0x34, 0x2e, 0x38, 0x2e, 0x30, 0x22, 0x2c, 0x22, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x22, 0x3a, 0x22, 0x4c, 0x6f, 0x74, 0x74, 0x69, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x41, 0x45, 0x20, 0x31, 0x2e, 0x30, 0x2e, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x64, 0x22, 0x3a, 0x22, 0x22, 0x2c, 0x22, 0x74, 0x63, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x2c, 0x22, 0x66, 0x72, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x77, 0x22, 0x3a, 0x37, 0x32, 0x30, 0x2c, 0x22, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x30, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x2c, 0x22, 0x64, 0x64, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x2c, 0x22, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x64, 0x64, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x34, 0x22, 0x2c, 0x22, 0x73, 0x72, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x31, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x30, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x33, 0x33, 0x36, 0x2c, 0x33, 0x39, 0x36, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x61, 0x6f, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x67, 0x72, 0x22, 0x2c, 0x22, 0x69, 0x74, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x68, 0x22, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x5b, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x5d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x5b, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x5d, 0x2c, 0x22, 0x76, 0x22, 0x3a, 0x5b, 0x5b, 0x2d, 0x31, 0x32, 0x33, 0x2c, 0x2d, 0x36, 0x36, 0x5d, 0x2c, 0x5b, 0x36, 0x2c, 0x34, 0x35, 0x5d, 0x2c, 0x5b, 0x33, 0x32, 0x31, 0x2c, 0x2d, 0x32, 0x36, 0x34, 0x5d, 0x5d, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x2d, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x22, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x39, 0x38, 0x30, 0x33, 0x39, 0x32, 0x31, 0x35, 0x36, 0x38, 0x36, 0x2c, 0x30, 0x2e, 0x36, 0x38, 0x36, 0x32, 0x37, 0x34, 0x35, 0x30, 0x39, 0x38, 0x30, 0x34, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x33, 0x37, 0x32, 0x35, + 0x34, 0x39, 0x30, 0x31, 0x39, 0x36, 0x2c, 0x31, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x77, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x35, 0x32, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6c, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6c, 0x6a, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x2d, 0x20, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x72, 0x22, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x37, 0x7d, 0x2c, 0x22, 0x73, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x73, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x70, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x63, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x33, 0x36, 0x38, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x31, 0x5d, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x35, 0x31, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x22, 0x3a, 0x34, 0x35, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x39, 0x32, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6d, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x69, 0x6d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x73, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x54, 0x72, 0x69, 0x6d, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x31, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x73, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x7b, 0x22, 0x64, 0x64, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x33, 0x22, 0x2c, 0x22, 0x73, 0x72, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x31, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x30, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x33, 0x33, 0x36, 0x2c, 0x33, 0x39, 0x36, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x61, 0x6f, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x67, 0x72, 0x22, 0x2c, 0x22, 0x69, 0x74, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x68, 0x22, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x5b, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x5d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x5b, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x5d, 0x2c, 0x22, 0x76, 0x22, 0x3a, 0x5b, 0x5b, 0x2d, 0x31, 0x32, 0x33, 0x2c, 0x2d, 0x36, 0x36, 0x5d, 0x2c, 0x5b, 0x36, 0x2c, 0x34, 0x35, 0x5d, 0x2c, 0x5b, 0x33, 0x32, 0x31, 0x2c, 0x2d, 0x32, 0x36, 0x34, 0x5d, 0x5d, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x2d, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x22, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x31, 0x39, 0x36, 0x30, 0x37, 0x38, 0x34, 0x33, 0x31, 0x33, 0x37, 0x2c, 0x30, 0x2e, 0x35, 0x35, 0x36, 0x38, 0x36, 0x32, 0x37, 0x34, 0x35, 0x30, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x32, 0x33, 0x35, 0x32, 0x39, 0x34, 0x31, 0x31, 0x37, 0x36, 0x34, 0x37, 0x2c, 0x31, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x77, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x34, 0x38, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6c, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6c, 0x6a, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, + 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x2d, 0x20, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x72, 0x22, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x37, 0x7d, 0x2c, 0x22, 0x73, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x73, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x70, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x63, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x33, 0x36, 0x38, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x31, 0x5d, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x35, 0x31, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x22, 0x3a, 0x34, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6d, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x69, 0x6d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x73, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x54, 0x72, 0x69, 0x6d, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x73, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x7b, 0x22, 0x64, 0x64, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, + 0x20, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x32, 0x22, 0x2c, 0x22, 0x73, 0x72, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x31, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x38, 0x37, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x30, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x33, 0x33, 0x36, 0x2c, 0x33, 0x36, 0x36, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x61, 0x6f, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x67, 0x72, 0x22, 0x2c, 0x22, 0x69, 0x74, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x64, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x35, 0x32, 0x30, 0x2c, 0x35, 0x32, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x2d, 0x20, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x22, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x39, 0x38, 0x30, 0x33, 0x39, 0x32, 0x31, 0x35, 0x36, 0x38, 0x36, 0x2c, 0x30, 0x2e, 0x36, 0x38, 0x36, 0x32, 0x37, 0x34, 0x35, 0x30, 0x39, 0x38, 0x30, 0x34, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x33, 0x37, 0x32, 0x35, 0x34, 0x39, 0x30, 0x31, 0x39, 0x36, 0x2c, 0x31, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x77, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x35, 0x32, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6c, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6c, 0x6a, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6c, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x2d, 0x20, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x72, 0x22, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, + 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x37, 0x7d, 0x2c, 0x22, 0x73, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x73, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x70, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x63, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x33, 0x33, 0x37, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x31, 0x5d, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x33, 0x33, 0x34, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x22, 0x3a, 0x34, 0x35, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x38, 0x30, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6d, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x69, 0x6d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x73, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x54, 0x72, 0x69, 0x6d, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x31, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x73, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x7b, 0x22, 0x64, 0x64, 0x64, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x72, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x31, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x38, 0x37, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x30, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x33, 0x33, 0x36, 0x2c, 0x33, 0x36, 0x36, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, + 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x61, 0x6f, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x68, 0x61, 0x70, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x67, 0x72, 0x22, 0x2c, 0x22, 0x69, 0x74, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x64, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x65, 0x6c, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x35, 0x32, 0x30, 0x2c, 0x35, 0x32, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x68, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x53, 0x68, 0x61, 0x70, 0x65, 0x20, 0x2d, 0x20, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x73, 0x74, 0x22, 0x2c, 0x22, 0x63, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x31, 0x39, 0x36, 0x30, 0x37, 0x38, 0x34, 0x33, 0x31, 0x33, 0x37, 0x2c, 0x30, 0x2e, 0x35, 0x35, 0x36, 0x38, 0x36, 0x32, 0x37, 0x34, 0x35, 0x30, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x32, 0x33, 0x35, 0x32, 0x39, 0x34, 0x31, 0x31, 0x37, 0x36, 0x34, 0x37, 0x2c, 0x31, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x77, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x34, 0x38, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6c, 0x63, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6c, 0x6a, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6c, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x2d, 0x20, 0x53, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x72, 0x22, 0x2c, 0x22, 0x70, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x30, 0x2c, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x31, 0x30, 0x30, 0x2c, 0x31, 0x30, 0x30, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x72, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x36, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x31, 0x30, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x37, 0x7d, 0x2c, 0x22, 0x73, 0x6b, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x34, 0x7d, 0x2c, 0x22, 0x73, 0x61, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x35, 0x7d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x45, + 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x65, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x70, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x63, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x74, 0x6d, 0x22, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x33, 0x36, 0x38, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x31, 0x5d, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x32, 0x35, 0x31, 0x5d, 0x2c, 0x22, 0x79, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x2c, 0x7b, 0x22, 0x74, 0x22, 0x3a, 0x34, 0x30, 0x2c, 0x22, 0x73, 0x22, 0x3a, 0x5b, 0x38, 0x34, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x7d, 0x2c, 0x22, 0x6f, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x33, 0x7d, 0x2c, 0x22, 0x6d, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x69, 0x78, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x6e, 0x6d, 0x22, 0x3a, 0x22, 0x54, 0x72, 0x69, 0x6d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x73, 0x20, 0x31, 0x22, 0x2c, 0x22, 0x6d, 0x6e, 0x22, 0x3a, 0x22, 0x41, 0x44, 0x42, 0x45, 0x20, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x54, 0x72, 0x69, 0x6d, 0x22, 0x2c, 0x22, 0x68, 0x64, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x7d, 0x5d, 0x2c, 0x22, 0x69, 0x70, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6f, 0x70, 0x22, 0x3a, 0x36, 0x30, 0x2c, 0x22, 0x73, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x6d, 0x22, 0x3a, 0x30, 0x7d, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, + 0x00 /*Close the string*/ +}; + +#endif diff --git a/examples/libs/rlottie/lv_example_rlottie_approve.json b/examples/libs/rlottie/lv_example_rlottie_approve.json new file mode 100644 index 000000000..6bd4d52c2 --- /dev/null +++ b/examples/libs/rlottie/lv_example_rlottie_approve.json @@ -0,0 +1 @@ +{"v":"4.8.0","meta":{"g":"LottieFiles AE 1.0.0","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":60,"w":720,"h":720,"nm":"Success","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[336,396,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-123,-66],[6,45],[321,-264]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.298039215686,0.686274509804,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":52,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.368],"y":[1]},"o":{"x":[0.251],"y":[0]},"t":10,"s":[0]},{"t":45,"s":[92]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[336,396,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-123,-66],[6,45],[321,-264]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.219607843137,0.556862745098,0.235294117647,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":48,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.368],"y":[1]},"o":{"x":[0.251],"y":[0]},"t":0,"s":[0]},{"t":40,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":87,"ix":10},"p":{"a":0,"k":[336,366,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[520,520],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.298039215686,0.686274509804,0.313725490196,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":52,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.337],"y":[1]},"o":{"x":[0.334],"y":[0]},"t":10,"s":[0]},{"t":45,"s":[80]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":10,"op":60,"st":10,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":87,"ix":10},"p":{"a":0,"k":[336,366,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[520,520],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.219607843137,0.556862745098,0.235294117647,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":48,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.368],"y":[1]},"o":{"x":[0.251],"y":[0]},"t":0,"s":[0]},{"t":40,"s":[84]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/lv_conf_template.h b/lv_conf_template.h index 560539337..66253d223 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -564,6 +564,9 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ # define LV_FREETYPE_CACHE_SIZE (16 * 1024) #endif +/*Rlottie library*/ +#define LV_USE_RLOTTIE 0 + /*----------- * Others *----------*/ diff --git a/scripts/filetohex.py b/scripts/filetohex.py new file mode 100755 index 000000000..73ad5a972 --- /dev/null +++ b/scripts/filetohex.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1], 'r') as file: + s = file.read() + +b = bytearray() +b.extend(map(ord, s)) + +for a in b: print(hex(a), end =", ") + diff --git a/src/extra/libs/lv_libs.h b/src/extra/libs/lv_libs.h index 7288aa51d..9ee861ee8 100644 --- a/src/extra/libs/lv_libs.h +++ b/src/extra/libs/lv_libs.h @@ -20,6 +20,7 @@ extern "C" { #include "qrcode/lv_qrcode.h" #include "sjpg/lv_sjpg.h" #include "freetype/lv_freetype.h" +#include "rlottie/lv_rlottie.h" /********************* * DEFINES diff --git a/src/extra/libs/rlottie/lv_rlottie.c b/src/extra/libs/rlottie/lv_rlottie.c new file mode 100644 index 000000000..bebebb0bc --- /dev/null +++ b/src/extra/libs/rlottie/lv_rlottie.c @@ -0,0 +1,183 @@ +/** + * @file lv_rlottie.c + * + */ + + /********************* + * INCLUDES + *********************/ + +#include "lv_rlottie.h" +#if LV_USE_RLOTTIE + +/********************* +* DEFINES +*********************/ +#define MY_CLASS &lv_rlottie_class + +/********************** +* TYPEDEFS +**********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void next_frame_task_cb(lv_timer_t* t); + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_rlottie_class = { + .constructor_cb = lv_rlottie_constructor, + .destructor_cb = lv_rlottie_destructor, + .instance_size = sizeof(lv_rlottie_t), + .base_class = &lv_img_class +}; + +static lv_coord_t create_width; +static lv_coord_t create_height; +static const char* rlottie_desc_create; +static const char* path_create; + +/********************** + * MACROS + **********************/ + + /********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t* lv_rlottie_create_from_file(lv_obj_t* parent, lv_coord_t width, lv_coord_t height, const char* path) +{ + + create_width = width; + create_height = height; + path_create = path; + rlottie_desc_create = NULL; + + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + + return obj; + +} + +lv_obj_t* lv_rlottie_create_from_raw(lv_obj_t* parent, lv_coord_t width, lv_coord_t height, const char* rlottie_desc) +{ + + create_width = width; + create_height = height; + rlottie_desc_create = rlottie_desc; + path_create = NULL; + + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent); + lv_obj_class_init_obj(obj); + + return obj; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_rlottie_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + + if(rlottie_desc_create) { + rlottie->animation = lottie_animation_from_data(rlottie_desc_create, rlottie_desc_create,""); + } + else if(path_create) { + rlottie->animation = lottie_animation_from_file(path_create); + } + if (rlottie->animation == NULL) { + LV_LOG_WARN("The aniamtion can't be opened"); + return; + } + + rlottie->total_frames = lottie_animation_get_totalframe(rlottie->animation); + rlottie->framerate = lottie_animation_get_framerate(rlottie->animation); + rlottie->current_frame = 0; + + lv_obj_t * parent = lv_obj_get_parent(obj); + + rlottie->scanline_width = create_width * LV_COLOR_DEPTH / 8; + + size_t allocaled_buf_size = (create_width * create_height * LV_COLOR_DEPTH / 8); + rlottie->allocated_buf = lv_mem_alloc(allocaled_buf_size); + if (rlottie->allocated_buf != NULL) + { + rlottie->allocated_buffer_size = allocaled_buf_size; + memset(rlottie->allocated_buf, 0, allocaled_buf_size); + } + + rlottie->imgdsc.header.always_zero = 0; + rlottie->imgdsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + rlottie->imgdsc.header.h = create_height; + rlottie->imgdsc.header.w = create_width; + rlottie->imgdsc.data = rlottie->allocated_buf; + rlottie->imgdsc.data_size = allocaled_buf_size; + + lv_img_set_src(obj, &rlottie->imgdsc); + + rlottie->task = lv_timer_create(next_frame_task_cb, 1000 / rlottie->framerate, obj); + + lv_obj_update_layout(obj); +} + + +static void lv_rlottie_destructor(const lv_obj_class_t * class_p, lv_obj_t* obj) +{ + + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + + if (rlottie->animation) { + lottie_animation_destroy(rlottie->animation); + rlottie->animation = 0; + rlottie->current_frame = 0; + rlottie->framerate = 0; + rlottie->scanline_width = 0; + rlottie->total_frames = 0; + } + + if (rlottie->task){ + lv_timer_del(rlottie->task); + rlottie->task = NULL; + } + + if (rlottie->allocated_buf) { + lv_mem_free(rlottie->allocated_buf); + rlottie->allocated_buf = NULL; + rlottie->allocated_buffer_size = 0; + } + +} + +static void next_frame_task_cb(lv_timer_t* t) +{ + lv_obj_t* obj = t->user_data; + lv_rlottie_t * rlottie = (lv_rlottie_t *) obj; + if (rlottie->current_frame == rlottie->total_frames) + rlottie->current_frame = 0; + else + ++rlottie->current_frame; + + lottie_animation_render( + rlottie->animation, + rlottie->current_frame, + rlottie->allocated_buf, + rlottie->imgdsc.header.w, + rlottie->imgdsc.header.h, + rlottie->scanline_width + ); + + lv_obj_invalidate(obj); + +} + +#endif /*LV_USE_RLOTTIE*/ diff --git a/src/extra/libs/rlottie/lv_rlottie.h b/src/extra/libs/rlottie/lv_rlottie.h new file mode 100644 index 000000000..46b3ed567 --- /dev/null +++ b/src/extra/libs/rlottie/lv_rlottie.h @@ -0,0 +1,61 @@ +/** + * @file lv_rlottie.h + * + */ + +#ifndef LV_RLOTTIE_H +#define LV_RLOTTIE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../../../lvgl.h" +#if LV_USE_RLOTTIE + +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_img_t img_ext; + Lottie_Animation* animation; + lv_timer_t* task; + lv_img_dsc_t imgdsc; + size_t total_frames; + size_t current_frame; + size_t framerate; + uint32_t* allocated_buf; + size_t allocated_buffer_size; + size_t scanline_width; +}lv_rlottie_t; + +extern const lv_obj_class_t lv_rlottie_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +lv_obj_t * lv_rlottie_create_from_file(lv_obj_t * parent,lv_coord_t width, lv_coord_t height, const char * path); + +lv_obj_t* lv_rlottie_create_from_raw(lv_obj_t* parent, lv_coord_t width, lv_coord_t height, const char* rlottie_desc); + +/********************** + * MACROS + **********************/ + +#endif /*LV_USE_RLOTTIE*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_RLOTTIE_H*/ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 4916fa8f7..2528e283a 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -1644,6 +1644,15 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #endif #endif +/*Rlottie library*/ +#ifndef LV_USE_RLOTTIE +# ifdef CONFIG_LV_USE_RLOTTIE +# define LV_USE_RLOTTIE CONFIG_LV_USE_RLOTTIE +# else +# define LV_USE_RLOTTIE 0 +# endif +#endif + /*----------- * Others *----------*/