diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c index 675eacb..cbd6ea0 100644 --- a/Core/Src/stm32f4xx_it.c +++ b/Core/Src/stm32f4xx_it.c @@ -22,6 +22,7 @@ #include "stm32f4xx_it.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "sgl.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -71,8 +72,8 @@ extern TIM_HandleTypeDef htim6; /* Cortex-M4 Processor Interruption and Exception Handlers */ /******************************************************************************/ /** - * @brief This function handles Non maskable interrupt. - */ + * @brief This function handles Non maskable interrupt. + */ void NMI_Handler(void) { /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ @@ -86,8 +87,8 @@ void NMI_Handler(void) } /** - * @brief This function handles Hard fault interrupt. - */ + * @brief This function handles Hard fault interrupt. + */ void HardFault_Handler(void) { /* USER CODE BEGIN HardFault_IRQn 0 */ @@ -101,8 +102,8 @@ void HardFault_Handler(void) } /** - * @brief This function handles Memory management fault. - */ + * @brief This function handles Memory management fault. + */ void MemManage_Handler(void) { /* USER CODE BEGIN MemoryManagement_IRQn 0 */ @@ -116,8 +117,8 @@ void MemManage_Handler(void) } /** - * @brief This function handles Pre-fetch fault, memory access fault. - */ + * @brief This function handles Pre-fetch fault, memory access fault. + */ void BusFault_Handler(void) { /* USER CODE BEGIN BusFault_IRQn 0 */ @@ -131,8 +132,8 @@ void BusFault_Handler(void) } /** - * @brief This function handles Undefined instruction or illegal state. - */ + * @brief This function handles Undefined instruction or illegal state. + */ void UsageFault_Handler(void) { /* USER CODE BEGIN UsageFault_IRQn 0 */ @@ -146,8 +147,8 @@ void UsageFault_Handler(void) } /** - * @brief This function handles Debug monitor. - */ + * @brief This function handles Debug monitor. + */ void DebugMon_Handler(void) { /* USER CODE BEGIN DebugMonitor_IRQn 0 */ @@ -166,8 +167,8 @@ void DebugMon_Handler(void) /******************************************************************************/ /** - * @brief This function handles USART1 global interrupt. - */ + * @brief This function handles USART1 global interrupt. + */ void USART1_IRQHandler(void) { /* USER CODE BEGIN USART1_IRQn 0 */ @@ -186,12 +187,12 @@ void USART1_IRQHandler(void) } /** - * @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts. - */ + * @brief This function handles TIM6 global interrupt, DAC1 and DAC2 underrun error interrupts. + */ void TIM6_DAC_IRQHandler(void) { /* USER CODE BEGIN TIM6_DAC_IRQn 0 */ - + sgl_tick_inc(1); /* USER CODE END TIM6_DAC_IRQn 0 */ HAL_TIM_IRQHandler(&htim6); /* USER CODE BEGIN TIM6_DAC_IRQn 1 */ @@ -200,8 +201,8 @@ void TIM6_DAC_IRQHandler(void) } /** - * @brief This function handles DMA2 stream2 global interrupt. - */ + * @brief This function handles DMA2 stream2 global interrupt. + */ void DMA2_Stream2_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream2_IRQn 0 */ @@ -214,8 +215,8 @@ void DMA2_Stream2_IRQHandler(void) } /** - * @brief This function handles DMA2 stream3 global interrupt. - */ + * @brief This function handles DMA2 stream3 global interrupt. + */ void DMA2_Stream3_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream3_IRQn 0 */ @@ -227,8 +228,8 @@ void DMA2_Stream3_IRQHandler(void) } /** - * @brief This function handles USB On The Go FS global interrupt. - */ + * @brief This function handles USB On The Go FS global interrupt. + */ void OTG_FS_IRQHandler(void) { /* USER CODE BEGIN OTG_FS_IRQn 0 */ @@ -241,8 +242,8 @@ void OTG_FS_IRQHandler(void) } /** - * @brief This function handles DMA2 stream6 global interrupt. - */ + * @brief This function handles DMA2 stream6 global interrupt. + */ void DMA2_Stream6_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream6_IRQn 0 */ @@ -254,8 +255,8 @@ void DMA2_Stream6_IRQHandler(void) } /** - * @brief This function handles DMA2 stream7 global interrupt. - */ + * @brief This function handles DMA2 stream7 global interrupt. + */ void DMA2_Stream7_IRQHandler(void) { /* USER CODE BEGIN DMA2_Stream7_IRQn 0 */ diff --git a/MDK-ARM/freertos_f407.uvoptx b/MDK-ARM/freertos_f407.uvoptx index 41e1ef1..f1045b4 100644 --- a/MDK-ARM/freertos_f407.uvoptx +++ b/MDK-ARM/freertos_f407.uvoptx @@ -200,6 +200,11 @@ 1 hspi3,0x10 + + 9 + 1 + sgl_system + @@ -283,7 +288,7 @@ Application/User/Core - 0 + 1 0 0 0 @@ -1315,7 +1320,7 @@ User/system/lib/lcd - 1 + 0 0 0 0 @@ -1479,7 +1484,7 @@ User/system/little_shell - 1 + 0 0 0 0 @@ -1545,6 +1550,422 @@ + + User/system/sgl + 1 + 0 + 0 + 0 + + 19 + 96 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_core.c + sgl_core.c + 0 + 0 + + + 19 + 97 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_anim.c + sgl_anim.c + 0 + 0 + + + 19 + 98 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_event.c + sgl_event.c + 0 + 0 + + + 19 + 99 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_log.c + sgl_log.c + 0 + 0 + + + 19 + 100 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_math.c + sgl_math.c + 0 + 0 + + + 19 + 101 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_misc.c + sgl_misc.c + 0 + 0 + + + 19 + 102 + 1 + 0 + 0 + 0 + ..\User\system\sgl\core\sgl_snprintf.c + sgl_snprintf.c + 0 + 0 + + + 19 + 103 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_arc.c + sgl_draw_arc.c + 0 + 0 + + + 19 + 104 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_circle.c + sgl_draw_circle.c + 0 + 0 + + + 19 + 105 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_icon.c + sgl_draw_icon.c + 0 + 0 + + + 19 + 106 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_line.c + sgl_draw_line.c + 0 + 0 + + + 19 + 107 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_rect.c + sgl_draw_rect.c + 0 + 0 + + + 19 + 108 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_ring.c + sgl_draw_ring.c + 0 + 0 + + + 19 + 109 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_text.c + sgl_draw_text.c + 0 + 0 + + + 19 + 110 + 1 + 0 + 0 + 0 + ..\User\system\sgl\draw\sgl_draw_xform.c + sgl_draw_xform.c + 0 + 0 + + + 19 + 111 + 1 + 0 + 0 + 0 + ..\User\system\sgl\fonts\sgl_ascii_song23.c + sgl_ascii_song23.c + 0 + 0 + + + 19 + 112 + 1 + 0 + 0 + 0 + ..\User\system\sgl\mm\lwmem\sgl_mm.c + sgl_mm.c + 0 + 0 + + + 19 + 113 + 1 + 0 + 0 + 0 + ..\User\system\sgl\mm\lwmem\lwmem.c + lwmem.c + 0 + 0 + + + 19 + 114 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\label\sgl_label.c + sgl_label.c + 0 + 0 + + + 19 + 115 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\line\sgl_line.c + sgl_line.c + 0 + 0 + + + 19 + 116 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\rectangle\sgl_rectangle.c + sgl_rectangle.c + 0 + 0 + + + 19 + 117 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\circle\sgl_circle.c + sgl_circle.c + 0 + 0 + + + 19 + 118 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\ring\sgl_ring.c + sgl_ring.c + 0 + 0 + + + 19 + 119 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\arc\sgl_arc.c + sgl_arc.c + 0 + 0 + + + 19 + 120 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\button\sgl_button.c + sgl_button.c + 0 + 0 + + + 19 + 121 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\slider\sgl_slider.c + sgl_slider.c + 0 + 0 + + + 19 + 122 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\progress\sgl_progress.c + sgl_progress.c + 0 + 0 + + + 19 + 123 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\switch\sgl_switch.c + sgl_switch.c + 0 + 0 + + + 19 + 124 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\msgbox\sgl_msgbox.c + sgl_msgbox.c + 0 + 0 + + + 19 + 125 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\textline\sgl_textline.c + sgl_textline.c + 0 + 0 + + + 19 + 126 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\textbox\sgl_textbox.c + sgl_textbox.c + 0 + 0 + + + 19 + 127 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\checkbox\sgl_checkbox.c + sgl_checkbox.c + 0 + 0 + + + 19 + 128 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\icon\sgl_icon.c + sgl_icon.c + 0 + 0 + + + 19 + 129 + 1 + 0 + 0 + 0 + ..\User\system\sgl\widgets\numberkbd\sgl_numberkbd.c + sgl_numberkbd.c + 0 + 0 + + + ::CMSIS 0 diff --git a/MDK-ARM/freertos_f407.uvprojx b/MDK-ARM/freertos_f407.uvprojx index 1b50b6a..a597ca1 100644 --- a/MDK-ARM/freertos_f407.uvprojx +++ b/MDK-ARM/freertos_f407.uvprojx @@ -339,7 +339,7 @@ --diag_suppress=68 --diag_suppress=111 --diag_suppress=188 --diag_suppress=223 --diag_suppress=546 --diag_suppress=1295 STM32,USE_HAL_DRIVER,STM32F407xx - ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/application;../User/board;../User/system;../User/system/lib/inc;../User/system/bsp;../FATFS/Target;../FATFS/App;../Middlewares/Third_Party/FatFs/src;../User/system/lib/lcd;../User/system/lib/lcd/gui/Config;../User/system/lib/lcd/gui/Core;../USB_DEVICE/App;../USB_DEVICE/Target;../Middlewares/ST/STM32_USB_Device_Library/Core/Inc;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc;../User/system/letter_shell + ../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/application;../User/board;../User/system;../User/system/lib/inc;../User/system/bsp;../FATFS/Target;../FATFS/App;../Middlewares/Third_Party/FatFs/src;../User/system/lib/lcd;../User/system/lib/lcd/gui/Config;../User/system/lib/lcd/gui/Core;../USB_DEVICE/App;../USB_DEVICE/Target;../Middlewares/ST/STM32_USB_Device_Library/Core/Inc;../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc;../User/system/letter_shell;..\User\system\sgl;..\User\system\sgl\include;..\User\system\sgl\widgets;..\User\system\sgl\mm\lwmem @@ -3621,6 +3621,181 @@ + + User/system/sgl + + + sgl_core.c + 1 + ..\User\system\sgl\core\sgl_core.c + + + sgl_anim.c + 1 + ..\User\system\sgl\core\sgl_anim.c + + + sgl_event.c + 1 + ..\User\system\sgl\core\sgl_event.c + + + sgl_log.c + 1 + ..\User\system\sgl\core\sgl_log.c + + + sgl_math.c + 1 + ..\User\system\sgl\core\sgl_math.c + + + sgl_misc.c + 1 + ..\User\system\sgl\core\sgl_misc.c + + + sgl_snprintf.c + 1 + ..\User\system\sgl\core\sgl_snprintf.c + + + sgl_draw_arc.c + 1 + ..\User\system\sgl\draw\sgl_draw_arc.c + + + sgl_draw_circle.c + 1 + ..\User\system\sgl\draw\sgl_draw_circle.c + + + sgl_draw_icon.c + 1 + ..\User\system\sgl\draw\sgl_draw_icon.c + + + sgl_draw_line.c + 1 + ..\User\system\sgl\draw\sgl_draw_line.c + + + sgl_draw_rect.c + 1 + ..\User\system\sgl\draw\sgl_draw_rect.c + + + sgl_draw_ring.c + 1 + ..\User\system\sgl\draw\sgl_draw_ring.c + + + sgl_draw_text.c + 1 + ..\User\system\sgl\draw\sgl_draw_text.c + + + sgl_draw_xform.c + 1 + ..\User\system\sgl\draw\sgl_draw_xform.c + + + sgl_ascii_song23.c + 1 + ..\User\system\sgl\fonts\sgl_ascii_song23.c + + + sgl_mm.c + 1 + ..\User\system\sgl\mm\lwmem\sgl_mm.c + + + lwmem.c + 1 + ..\User\system\sgl\mm\lwmem\lwmem.c + + + sgl_label.c + 1 + ..\User\system\sgl\widgets\label\sgl_label.c + + + sgl_line.c + 1 + ..\User\system\sgl\widgets\line\sgl_line.c + + + sgl_rectangle.c + 1 + ..\User\system\sgl\widgets\rectangle\sgl_rectangle.c + + + sgl_circle.c + 1 + ..\User\system\sgl\widgets\circle\sgl_circle.c + + + sgl_ring.c + 1 + ..\User\system\sgl\widgets\ring\sgl_ring.c + + + sgl_arc.c + 1 + ..\User\system\sgl\widgets\arc\sgl_arc.c + + + sgl_button.c + 1 + ..\User\system\sgl\widgets\button\sgl_button.c + + + sgl_slider.c + 1 + ..\User\system\sgl\widgets\slider\sgl_slider.c + + + sgl_progress.c + 1 + ..\User\system\sgl\widgets\progress\sgl_progress.c + + + sgl_switch.c + 1 + ..\User\system\sgl\widgets\switch\sgl_switch.c + + + sgl_msgbox.c + 1 + ..\User\system\sgl\widgets\msgbox\sgl_msgbox.c + + + sgl_textline.c + 1 + ..\User\system\sgl\widgets\textline\sgl_textline.c + + + sgl_textbox.c + 1 + ..\User\system\sgl\widgets\textbox\sgl_textbox.c + + + sgl_checkbox.c + 1 + ..\User\system\sgl\widgets\checkbox\sgl_checkbox.c + + + sgl_icon.c + 1 + ..\User\system\sgl\widgets\icon\sgl_icon.c + + + sgl_numberkbd.c + 1 + ..\User\system\sgl\widgets\numberkbd\sgl_numberkbd.c + + + ::CMSIS diff --git a/MDK-ARM/freertos_f407/freertos_f407.hex b/MDK-ARM/freertos_f407/freertos_f407.hex index 0975ca9..488e04d 100644 --- a/MDK-ARM/freertos_f407/freertos_f407.hex +++ b/MDK-ARM/freertos_f407/freertos_f407.hex @@ -1,8 +1,8 @@ :020000040800F2 -:10000000B019012061020008E5470008C343000859 -:10001000E14700089D090008818E000800000000EB +:10000000405601206102000805490008E344000849 +:1000100001490008BD0A0008B58F00080000000073 :10002000000000000000000000000000A101000826 -:10003000D30B000800000000FD010008A95B0008C8 +:10003000F30C000800000000FD010008C95C000886 :100040007B0200087B0200087B0200087B0200089C :100050007B0200087B0200087B0200087B0200088C :100060007B0200087B0200087B0200087B0200087C @@ -12,19 +12,19 @@ :1000A0007B0200087B0200087B0200087B0200083C :1000B0007B0200087B0200087B0200087B0200082C :1000C0007B0200087B0200087B0200087B0200081C -:1000D0007B020008616400087B0200087B020008C4 +:1000D0007B020008956500087B0200087B0200088F :1000E0007B0200087B0200087B0200087B020008FC :1000F0007B0200087B0200087B0200087B020008EC :100100007B0200087B0200087B0200087B020008DB -:100110007B0200087B020008A95C00087B02000843 -:100120007B0200087B020008890A0008990A00087F +:100110007B0200087B020008C95D00087B02000822 +:100120007B0200087B020008A90B0008B90B00083D :100130007B0200087B0200087B0200087B020008AB -:100140007B0200087B0200087B020008E9470008E8 -:100150007B020008A90A0008B90A00087B0200080F +:100140007B0200087B0200087B02000809490008C6 +:100150007B020008C90B0008D90B00087B020008CD :100160007B0200087B0200087B0200087B0200087B :100170007B0200087B0200087B02000800000000F0 -:100180007B0200087B020008DFF810D000F050FB73 -:100190000048004785A70008AFF30080B019012090 +:100180007B0200087B020008DFF810D000F0E0FBE3 +:100190000048004701AC0008AFF300804056012042 :1001A0002C4B19680868B0E8F04F80F30988BFF35A :1001B0006F8F4FF0000080F311887047000000003F :1001C00008480068006880F308884FF0000080F35A @@ -33,5457 +33,5666 @@ :1001F00070010160704700BF88ED00E0EFF30980F7 :10020000BFF36F8F134B1A681EF0100F08BF20ED5D :10021000108A20E9F04F106009B44FF0500080F3CD -:100220001188BFF34F8FBFF36F8F0DF03BFA4FF084 +:100220001188BFF34F8FBFF36F8F11F0A5FD4FF013 :10023000000080F3118809BC19680868B0E8F04F25 :100240001EF0100F08BFB0EC108A80F30988BFF3CE :100250006F8F704714000020EFF305807047000097 :100260000648804706480047FEE7FEE7FEE7FEE750 -:10027000FEE7FEE7FEE7FEE7FEE7FEE7955C000827 +:10027000FEE7FEE7FEE7FEE7FEE7FEE7B55D000806 :10028000890100082DE9F05F0546002092469B4653 :1002900088460646814640241BE02846414647469C -:1002A000224600F0A6F953465A46C01A914110D38F -:1002B00011461846224600F08DF92D1A67EB010809 -:1002C0004F4622460120002100F084F917EB000977 +:1002A000224600F036FA53465A46C01A914110D3FE +:1002B00011461846224600F01DFA2D1A67EB010878 +:1002C0004F4622460120002100F014FA17EB0009E6 :1002D0004E41201EA4F10104DFDC484631462A4687 -:1002E0004346BDE8F09F40EA01039B0703D009E0C5 -:1002F00008C9121F08C0042AFAD203E011F8013B12 -:1003000000F8013B521EF9D27047D2B201E000F86A -:10031000012B491EFBD270470022F6E710B51346A9 -:100320000A4604461946FFF7F0FF204610BD421C5E -:1003300010F8011B0029FBD1801A704710B500226C -:1003400000E0521C835C8C5CA34201D1002BF8D1ED -:10035000D8B2E1B2401A10BD30B5054600200346C0 -:1003600000E05B1C934205D2EC5CC85C201A01D112 -:10037000002CF6D130BD2DE9FE4F804681EA030006 -:10038000C00F0C46009021F0004123F00045B8EB6F -:100390000200A94105D24046214690461C460B4624 -:1003A000024623F00040104347D0270DC7F30A0050 -:1003B000C3F30A510290401A019040286BDAC3F34C -:1003C000130040F4801B0098924620B10023D2EB2A -:1003D000030A63EB0B0B01985946C0F140025046EB -:1003E00000F0F8F806460D4650465946019A00F0CE -:1003F00010F910EB08006141002487EA115284EAE9 -:10040000E7731A4340D0009A62B3019A012A4FEA77 -:10041000075215DC001B61EB02014FF0004202EABB -:100420000752CDE90042001C41F5801132462B46AF -:1004300000F010F903B0BDE8F08F40462146F9E71F -:10044000001B61EB0201001C41F5801300185B41A9 -:100450002018A2F5001747EB030140EAD570B61942 -:100460006D4111E06D084FEA360645EAC0754FEA66 -:100470000752001B61EB0201001C41F58011490885 -:100480004FEA30000019514132462B4603B0BDE817 -:10049000F04F00F0D0B80098012240000023D0EBCC -:1004A000020263EBE073009821464FEAE074B8EB78 -:1004B000000061EB0401E9E783F000435BE781F0B2 -:1004C000004158E72DE9FE4F81EA030404F000449F -:1004D00021F0004100944FF0000B23F0004350EA5C -:1004E00001045ED052EA03045BD0C3F30A54C1F3A3 -:1004F0000A552C44A4F2F3340194A0FB0254C1F336 -:10050000130141F48011C3F3130343F4801301FB7F -:10051000024400FB034E840A970A44EA815447EAE6 -:100520008357A4FB076802958D0A05FB07854FEAF0 -:10053000932C04FB0C542705029D4FEA065847EA0A -:100540001637B5EB08056EEB070C870E920E47EADF -:10055000811742EA8312A7FB0201B6EB0B0164EBA1 -:1005600000042B0D43EA0C335E1844EB1C50DA46B2 -:100570005146E7FB0201C5F313044FEA0B3343EA8C -:1005800014534FEA0432019C43EA0603A4F10C041D -:100590000294009CCDE900B400F05CF803B0BDE823 -:1005A000F08F00200146F9E730B50B4601460020E8 -:1005B0002022012409E021FA02F59D4205D303FA25 -:1005C00002F5491B04FA02F52844151EA2F10102A6 -:1005D000F1DC30BD202A04DB203A00FA02F10020D1 -:1005E00070479140C2F1200320FA03F31943904071 -:1005F0007047202A04DB203A21FA02F000217047DC -:1006000021FA02F3D040C2F120029140084319467A -:100610007047202A06DBCB17203A41FA02F043EA62 -:10062000E07306E041FA02F3D040C2F120029140AB -:1006300008431946704710B5141E73F1000408DA18 -:10064000401C41F1000192185B411A4301D120F096 -:10065000010010BD2DE9F04D92469B4611B1B1FA53 -:1006600081F202E0B0FA80F220329046FFF7B2FF4A -:1006700004460F4640EA0A0041EA0B0153465A4637 -:10068000084313D0114653EA010019D0C8F14002C3 -:100690005046FFF7AEFF05460E46504659464246C5 -:1006A000FFF798FF084305D0012004E020463946B3 -:1006B000BDE8F08D0020054346EAE0762C43374341 -:1006C0000A986305E40AA0EB08000022FD0A44EA48 -:1006D00047540A3002D500200146E9E70105101908 -:1006E0006941DDE9084500196941BDE8F04DA2E71F -:1006F0002DE9F04D81EA030404F0004B21F00045A0 -:1007000014464FF0000A23F0004150EA050220D0C1 -:1007100054EA01021DD0C5F30A570246C5F313037C -:10072000C1F31300C1F30A5640F4801543F480135B -:10073000A7EB0608101BD64608F2FD3873EB050040 -:1007400002D308F1010801E092185B41B8F1000FF3 -:1007500003DA00200146BDE8F08D00204FF480113F -:10076000064684460EE0171B73EB050705D3121BE4 -:1007700063EB050306434CEA010C49084FEA3000DD -:1007800092185B4150EA0107EDD152EA030012D002 -:1007900082EA040083EA0501084305D0101BAB413F -:1007A00006D20122002306E000224FF0004302E0BF -:1007B0006FF0010253101AEB06004CEB085110EBDE -:1007C0000A0041EB0B01BDE8F04DFFF734BFC1F368 -:1007D0000A52C1F3130140F2FF3341F480119A42EF -:1007E00002DA00200146704740F233439A42A2F2F7 -:1007F000334202DC5242FFF7FCBEFFF7EBBE0000C3 -:1008000030B5041E71F1000404DB4FF00044404297 -:1008100064EB0101141E73F1000405DB1C464FF06C -:100820000043524263EB0403994208BF904230BD3B -:10083000064C074D06E0E06840F0010394E807002D -:1008400098471034AC42F6D3FFF7A2FCEC530108F2 -:100850001C54010870B58C1810F8015B15F00703E3 -:1008600001D110F8013B2A1106D110F8012B03E049 -:1008700010F8016B01F8016B5B1EF9D12B0705D451 -:100880000023521E0DD401F8013BFAE710F8013B9A -:10089000CB1A921C03E013F8015B01F8015B521EB6 -:1008A000F9D5A142D8D3002070BD000010B50124B5 -:1008B000A102034800F03AFD00B10024204610BD1B -:1008C0000004024010B504462146024802F0DCFC58 -:1008D00010BD00000C05002010B5044802F0E7FC34 -:1008E000042801D0012010BD0020FCE70C050020E9 -:1008F00010B5002400F014F8012801D0012010BD2B -:10090000064802F0E6FC044634B94FF4006103489F -:1009100002F070FB00B101242046F0E70C05002036 -:1009200008B501200090FFF7C1FF08B90020009032 -:100930009DF8000008BD00002DE9F04104460D4679 -:100940001646002733462A462146044802F0F6FDA3 -:1009500000B101273846BDE8F08100000C050020F9 -:1009600010B500220121024800680AF0CFF810BD3E -:10097000A80000202DE9F04104460D461646002748 -:1009800033462A462146044802F086FE00B101277C -:100990003846BDE8F08100000C05002000BFFEE7EE -:1009A0000346042B15D007DC7BB1012B0ED0022BA4 -:1009B0000DD0032B12D10BE0202B0BD0212B0AD012 -:1009C000222B09D0232B09D107E008E007E006E03D -:1009D00005E004E003E002E001E000E000BF00BF4A -:1009E000002070470020704710B5002204490548D8 -:1009F00005F0EFFF0449034805F0DCFF002010BDBF -:100A00006C02012090F500206CFA002070B50446BD -:100A10000D46204629680CF02FFB2146034805F0BF -:100A2000C9FF024805F092FF002070BD90F500203C -:100A300010B503460C460021084610BD2DE9F041D3 -:100A400004460D4600260A48D0F8BC72D7F81402B6 -:100A500010B10120BDE8F0812A462146044805F086 -:100A6000B8FF034806F068F806463046F2E7000093 -:100A700090F50020024600BF1AB901E000BF00BF98 -:100A8000FCE700BF0120704710B5024800F060F994 -:100A900010BD0000EC06002010B5024800F058F927 -:100AA00010BD00009005002010B5024800F050F97C -:100AB00010BD0000F005002010B5024800F048F914 -:100AC00010BD00004C07002001460878103818239C -:100AD000B0FBF3F20848805CC865032A05D90868B2 -:100AE0006FF30900001D886503E008686FF30900D3 -:100AF0008865886D7047000088E70008014600207F -:100B00008A6A8B69CBB932B1012A0DD0022A03D08F -:100B1000032A10D10EE000BFCB6A03F08073B3F15B -:100B2000807F00D1012007E0CB6AB3F1C07F00D104 -:100B3000012001E000E000BF34E08B69B3F5005F05 -:100B40001AD132B1012A07D0022A03D0032A11D1C7 -:100B50000AE000BF01200EE0CB6A03F08073B3F11E -:100B6000807F00D1012006E0CB6AB3F1C07F00D1C5 -:100B7000012000E000BF15E032B1012A05D0022AB1 -:100B800004D0032A0CD103E000BF00BF012008E01D -:100B9000CB6A03F08073B3F1807F00D1012000E0C5 -:100BA00000BF00BF704730B50468246824F4802477 -:100BB00005682C60046863608468402C04D1046874 -:100BC000A2600468E16003E00468A1600468E26078 -:100BD00030BD704772B600BFFEE730B504460D4623 -:100BE00000222946204600F001F830BDF0B503464A -:100BF000012500241148807B02281CDA00200F4EBA -:100C0000B67B0E4FB8553846867B001D40F826301F -:100C1000001F867B0C3082553E46B07B461CBE735F -:100C2000044604F1300008703A2048702F20887084 -:100C30000020C87000252846F0BD000080F5002087 -:100C400070B50A480468001D0568001D0668344434 -:100C500054B108220649204603F0B5FB042204499A -:100C60001031284603F0AFFB70BD0000107AFF1F63 -:100C70006601002070B50446A56D00F06FFB0646C6 -:100C800094F83500022808D08020606500BF00205D -:100C900084F8340000BF012070BD2068006820F097 -:100CA0001600216808602068406920F080002168F3 -:100CB0004861206C08B9A06C28B12068006820F059 -:100CC0000800216808602068006820F001002168A1 -:100CD000086010E000F042FB801B05280BD92020A3 -:100CE0006065032084F8350000BF002084F83400DC -:100CF00000BF0320D0E72068006800F00100002852 -:100D0000E8D194F85C103F208840A860012084F866 -:100D1000350000BF002084F8340000BF00BFBBE7EF -:100D2000014691F83500022803D080204865012053 -:100D30007047052081F835000868006820F0010040 -:100D40000A6810600020F3E70146486D7047000014 -:100D5000F8B50446002000908C4800684FF4165106 -:100D6000B0FBF1F7A56D2E6894F85C100820884060 -:100D7000304098B12068006800F0040070B120682D -:100D8000006820F004002168086094F85C100820D6 -:100D90008840A860606D40F00100606594F85C10C8 -:100DA00001208840304068B12068406900F0800030 -:100DB00040B194F85C1001208840A860606D40F05C -:100DC0000200606594F85C1004208840304068B1EF -:100DD0002068006800F0020040B194F85C10042024 -:100DE0008840A860606D40F00400606594F85C1075 -:100DF00010208840304078B32068006800F0080078 -:100E000050B394F85C1010208840A86020680068F7 -:100E100000F4802080B12068006800F4002028B928 -:100E2000206CC8B12046216C884715E0A06C98B1B1 -:100E30002046A16C88470FE02068006800F48070AD -:100E400028B92068006820F0080021680860206C3C -:100E500010B12046216C884794F85C10202088400F -:100E60003040002865D02068006800F0100000289D -:100E70005FD094F85C1020208840A86094F835007A -:100E8000052828D12068006820F016002168086035 -:100E90002068406920F0800021684861206C08B912 -:100EA000A06C28B12068006820F008002168086064 -:100EB00094F85C103F208840A860012084F8350039 -:100EC00000BF002084F8340000BF206D10B1204620 -:100ED000216D8847F8BD2068006800F4802080B14B -:100EE0002068006800F4002028B9606C10B120462A -:100EF000616C88471DE0E06BD8B12046E16B884704 -:100F000017E02068006800F4807068B92068006805 -:100F100020F0100021680860012084F8350000BF2F -:100F2000002084F8340000BFE06B10B12046E16B74 -:100F30008847606D38B3606D00F00100F0B10520A6 -:100F400084F835002068006820F0010021680860FE -:100F500000BF0098401C0090B84200D905E020680E -:100F6000006800F001000028F3D100BF012084F8E0 -:100F7000350000BF002084F8340000BFE06C10B1E1 -:100F80002046E16C884700BFA4E700001000002065 -:100F90002DE9F0410446002500F0E0F9074614B9B8 -:100FA0000120BDE8F081606A00B100BF022084F832 -:100FB000350000BF002084F8340000BF20680068BE -:100FC00020F00100216808600AE000F0C7F9C01BAA -:100FD000052805D920206065032084F83500E0E766 -:100FE0002068006800F001000028EED12068056844 -:100FF00021480540D4E901010843E168084321691B -:10100000084361690843A1690843E1690843216A0B -:1010100008430543606A042803D1D4E90B0108435F -:101020000543206805602068456925F00705606A6A -:101030000543606A04280DD1A06A0543E06A48B1FF -:101040002046FFF75BFD28B140206065012084F851 -:101050003500A6E7206845612046FFF735FD0646C6 -:1010600094F85C103F208840B0600020606501204B -:1010700084F83500002094E73F8010F02DE9F04718 -:1010800004460D4616461F464FF00008D4F8589007 -:1010900000BF94F83400012802D10220BDE8F08797 -:1010A000012084F8340000BF94F83500012825D1D0 -:1010B000022084F83500002060653B463246294610 -:1010C0002046FFF770FD94F85C103F208840C9F877 -:1010D00008002068006840F0160021680860206C55 -:1010E00028B12068006840F0080021680860206886 -:1010F000006840F001002168086006E000BF0020A1 -:1011000084F8340000BF4FF002084046C6E70000F4 -:1011100070B5044600F022F906462546681C10B159 -:1011200004480078054400BF00F018F9801BA8426D -:10113000FAD370BD0C000020F8B502460B4600251E -:10114000002400200021D6E0012606FA01F51E68E1 -:1011500006EA0504AC4274D11E7906F00306012E9E -:1011600004D01E7906F00306022E13D190684F00BA -:101170000326BE40B0434F00DE68BE40304390605F -:10118000506801268E40B0431E79C6F300168E408B -:10119000304350601E7906F00306032E09D0D06854 -:1011A0004F000326BE40B0434F009E68BE40304310 -:1011B000D0601E7906F00306022E13D1CF0802F18B -:1011C000200656F827004E07F70E0F26BE40B04304 -:1011D0004F07FF0E1E69BE403043CF0802F12006C4 -:1011E00046F8270010684F000326BE40B0431E7922 -:1011F00006F003064F00BE40304310605E6806F400 -:101200004036002E76D000BF002600963C4E366851 -:1012100046F480463A4F3E603E46366806F48046C5 -:10122000009600BF00BF374E8F0856F827008E0784 -:10123000370F0F26BE40B043334EB24202D10026D4 -:1012400024E057E0314EB24201D101261EE0304E7B -:10125000B24201D1022619E02E4EB24201D103263C -:1012600014E02D4EB24201D104260FE02B4EB242C3 -:1012700001D105260AE02A4EB24201D1062605E038 -:10128000284EB24201D1072600E008268F073F0F03 -:10129000BE4030431B4E8F0846F82700224E306870 -:1012A000A0435E6806F4801606B120431E4E3060EF -:1012B000361D3068A0435E6806F4001606B1204370 -:1012C000194E361D3060184E361F3068A0435E68D8 -:1012D00006F4003606B12043134E361F3060361F29 -:1012E0003068A0435E6806F4803606B120430E4E97 -:1012F000083E3060491C1029FFF426AFF8BD0000FD -:101300004438024008380140000002400004024016 -:1013100000080240000C024000100240001402408D -:1013200000180240001C0240083C014002461369BC -:101330000B400BB1012000E00020704710B542695E -:1013400021EA020302EA010443EA0443836110BD77 -:101350000AB1816101E00B048361704701480068B4 -:101360007047000004000020034800680349097822 -:101370000844014908607047040000200C00002068 -:1013800010B50D48006840F400700B49086008462D -:10139000006840F4806008600846006840F480708F -:1013A0000860032000F0DCF8042000F007F800F0EB -:1013B0005FF8002010BD0000003C02402DE9F04124 -:1013C00088B004460027B84600BF0020019023489B -:1013D000006840F01000214908600846006800F0ED -:1013E0001000019000BF00BF02A903A801F052F94C -:1013F000069F1FB901F076F9054602E001F072F987 -:1014000045001748B5FBF0F0A0F101081548164952 -:10141000086040F2E7311448C160C0F80480002140 -:1014200001618160816102F0A0FB064696B90E4819 -:1014300002F0D0FB06466EB9362000F043F8102CBF -:1014400007D200222146362000F04CF807480460FD -:1014500000E00126304608B0BDE8F0814038024087 -:1014600040420F0000100040AC07002008000020A0 -:1014700008B500BF002000901148006840F480408B -:101480000F4908600846006800F48040009000BFE3 -:1014900000BF00BF00200090081F006840F080508F -:1014A000091F08600846006800F08050009000BFE7 -:1014B00000BF00220F21901E00F014F808BD0000AC -:1014C0004438024001460846002809DB00F01F03AB -:1014D00001229A4043099B0003F1E023C3F8002155 -:1014E00000BF70472DE9F05F80460D461646002785 -:1014F00007F0F6FC074639462A46334601F0070056 -:10150000C0F1070ABAF1040F02D94FF0040A01E052 -:10151000C0F1070AD14600F1040ABAF1070F02D25E -:101520004FF0000A01E0A0F1030AD4464FF0010A8F -:101530000AFA09FAAAF1010A0AEA020A0AFA0CFAF4 -:101540004FF0010B0BFA0CFBABF1010B0BEA030B99 -:101550004AEA0B042146404607F0CAFCBDE8F09F6A -:1015600000BF00F00702064B19684FF6FF03194051 -:10157000044B0B4343EA0221014B196000BF704743 -:101580000CED00E00000FA05704702461068416269 -:1015900000207047F0B5034615461868446A21B923 -:1015A00044EA05401E68B06219E01868806A04EBDE -:1015B0001044002208E0186800F5827050F82200FC -:1015C00004EB1044501CC2B2481E9042F3D844EAC7 -:1015D0000547186800F582704E1E40F826700020FE -:1015E000F0BD10B50446D4F8080505F010FF10BD95 -:1015F00070B504460D4605EBC50304F13C0101EB53 -:1016000083010A692946D4F8080505F0FBFD70BD81 -:1016100070B504460D4605EBC50304F51F7101EBDB -:1016200083010A692946D4F8080505F06FFE70BDEC -:1016300010B50446D4F8080505F0ECFE10BD2DE900 -:10164000F04104460D4605F08000802808D105F0E1 -:101650000F0000EBC00104F13C0000EB810607E045 -:1016600005F00F0000EBC00104F51F7000EB8106D0 -:101670003146206807F0C0F907463846BDE8F081DA -:1016800070B504460E4606F0800080280AD106F0A8 -:101690000F0000EBC00104F13C0000EB81050120CC -:1016A000687009E006F00F0000EBC00104F51F7040 -:1016B00000EB81050020687006F00F00287000BF65 -:1016C00094F8BC04012801D1022070BD012084F8E7 -:1016D000BC0400BF2946206806F06EFC00BF002055 -:1016E00084F8BC0400BF00BFEFE770B504460E46A7 -:1016F00006F00F006168884201D9012070BD06F034 -:10170000800080280AD106F00F0000EBC00104F130 -:101710003C0000EB81050120687009E006F00F0035 -:1017200000EBC00104F51F7000EB8105002068701C -:101730000020A87006F00F00287000BF94F8BC04C9 -:10174000012801D10220D9E7012084F8BC0400BFA0 -:101750002946206806F018FF00BF002084F8BC046A -:1017600000BF00BFCAE7024601F00F0000EBC00354 -:1017700002F51F7000EB8300006A70472DE9F04707 -:1017800005460E4690461F464FF0000906F08000C1 -:1017900080280AD106F00F0000EBC00105F13C00E3 -:1017A00000EB81040120607009E006F00F0000EBFF -:1017B000C00105F51F7000EB81040020607006F089 -:1017C0000F002070C4F80C802771607808B1207871 -:1017D0002081022F01D10020607100BF95F8BC0468 -:1017E000012802D10220BDE8F087012085F8BC0461 -:1017F00000BF2146286806F0F5FA00BF002085F8F2 -:10180000BC0400BF4846EEE72DE9F04104460E4611 -:101810001746984606F00F0000EBC00104F51F7054 -:1018200000EB81052F61C5F81880002028626870E0 -:1018300006F00F0028702069012800D16F6106F0C2 -:101840000F0028B9227C2946206806F077FD04E0C5 -:10185000227C2946206806F02BFF0020BDE8F0819D -:1018600070B504460D4605F00F006168884201D945 -:10187000012070BD05F0800080280AD105F00F001E -:1018800000EBC00104F13C0000EB81060120707008 -:1018900007E005EBC50104F51F7000EB8106002091 -:1018A00070700120B07005F00F00307000BF94F828 -:1018B000BC04012801D10220DBE7012084F8BC042C -:1018C00000BF3146206806F0A6FE05F00F0028B9DB -:1018D000217C04F2C442206806F01EFE00BF0020F6 -:1018E00084F8BC0400BF00BFC3E72DE9F041044603 -:1018F0000E461746984606F00F0000EBC00104F1B3 -:101900003C0000EB81052F61C5F81880002028629B -:101910000120687006F00F0028702069012800D1AE -:101920006F6106F00F0028B9227C2946206806F076 -:1019300005FD04E0227C2946206806F0B9FE00205F -:10194000BDE8F0812DE9FE4F0446D4F800B05E46B4 -:10195000206807F038F9002874D1206807F072F980 -:1019600008B9BDE8FE8F40F608008059C0F30D208D -:10197000C4F8FC04206807F065F900F002000228B2 -:1019800005D12068406900F00200216848612068A4 -:1019900007F058F900F01000102845D12068806940 -:1019A00020F0100021688861DBF8209009F00F001A -:1019B00000EBC00104F51F7000EB810AC9F343403E -:1019C00002281AD147F6F07009EA000030B3C9F3D3 -:1019D0000A125846DAF8101007F039F9C9F30A115B -:1019E000DAF810000844CAF81000C9F30A11DAF84E -:1019F00020000844CAF8200010E0C9F3434006283C -:101A00000CD1082204F2C441584607F020F9C9F36A -:101A10000A11DAF820000844CAF82000206880691A -:101A200040F0100021688861206807F00BF900F48D -:101A30000020B0F5002F7BD10025206807F0D2F8F8 -:101A4000029072E0E1E2029800F00100002868D004 -:101A5000E9B2206807F0E9F8804608F0010048B1D3 -:101A6000012106F5306000EB4510816029462046D3 -:101A700002F0F4FE08F00800082809D1082106F554 -:101A8000306000EB451081602946204602F0B4FE2C -:101A900008F01000102805D1102106F5306000EB89 -:101AA0004510816008F00200022824D1DBF8140000 -:101AB00000F08000802807D140F60400805940F4EF -:101AC000806140F60400815105EBC50104F51F70EB -:101AD00000EB810A9AF80300012806D100208AF859 -:101AE0000300E9B2204600F09BFA022106F53060BF -:101AF00000EB4510816008F02000202805D120214E -:101B000006F5306000EB4510816008F40050B0F538 -:101B1000005F06D14FF4005106F5306000EB451030 -:101B200081606D1C029840080290029800288AD1BA -:101B3000206807F087F800F48020B0F5802F7DD171 -:101B4000206807F045F8029000259AE0029800F01E -:101B50000100002873D0E9B2206807F04DF88046F4 -:101B600008F00100F0B305F00F010120884001905A -:101B700040F634008159019821EA000040F6340112 -:101B80008851012106F5106000EB45108160206945 -:101B9000012824D105EBC50104F13C0000EB8100D4 -:101BA00005EBC502016904F13C0000EB8200C0684E -:101BB000014405EBC50204F13C0000EB8200016129 -:101BC0006DB905EBC50104F13C0000EB81008069B3 -:101BD00028B904F2C4420121206806F09DFCE9B254 -:101BE000204600E001E0FFF703FD08F008000828A8 -:101BF00005D1082106F5106000EB4510816008F062 -:101C00001000102805D1102106F5106000EB4510DA -:101C1000816008F04000402805D1402106F51060A1 -:101C200000EB4510816008F0020002281DD1294612 -:101C3000584606F089FF05EBC50101E025E01CE0F0 -:101C400004F13C0000EB810A9AF80300012806D158 -:101C500000208AF80300E9B2204600F0D8F90221FA -:101C600006F5106000EB4510816008F080008028C8 -:101C700003D12946204602F093FE6D1C02984008CD -:101C80000290029800287FF461AF206806F0DAFF26 -:101C900000F00040B0F1004F1CD140F60400805924 -:101CA00020F0010140F60400815194F8F404012869 -:101CB00007D1002084F8F40400212046FFF764FCDB -:101CC00002E0204600F0D4FA2068406900F00040AD -:101CD00021684861206806F0B5FF00F40060B0F5A7 -:101CE000006F0ED140F60800805900F0010010B1DD -:101CF000204600F015FB2068406900F40060216870 -:101D00004861206806F09EFF00F48050B0F5805FC7 -:101D10007ED140F60400805920F0010140F6040015 -:101D200081511021206806F00FFF002732E04FF6A6 -:101D30007F3106F5106000EB4710816006F51060FA -:101D400000EB4710006820F4001106F5106000EB6E -:101D5000471001604FF67F3106F5306000EB471009 -:101D6000816006F5306000EB4710006820F4001138 -:101D700006F5306000EB4710016006F5306000EBBF -:101D80004710006840F0006106F5306000EB471036 -:101D900001607F1C6068B842C9D840F61C008059B9 -:101DA00040F0011140F61C008151206B70B1D6F853 -:101DB000840840F00B01C6F8841840F644008059AE -:101DC00040F00B0140F6440081510FE040F6140052 -:101DD000805942F22B01084340F614018851081F34 -:101DE000805940F00B014FF401608151D6F8000892 -:101DF00020F4FE60C6F80008217C04F2C44220688A -:101E000006F08AFB2068406900F48050216800E0F9 -:101E100000E04861206806F015FF00F40050B0F5BE -:101E2000005F17D1206806F045F8206806F0B8FE7C -:101E3000E06000F051FC0090227B2068009906F0E1 -:101E400089FF204600F0FCF92068406900F400504A -:101E500021684861206806F0F5FE00F008000828B7 -:101E600008D1204600F00BFA2068406900F0080015 -:101E700021684861206806F0E5FE00F080008028B7 -:101E800018D1DBF8180020F08000CBF818000125ED -:101E90000DE005EBC50104F51F7000EB8100C07873 -:101EA000012803D1E9B22046FFF7C9FB6D1C606829 -:101EB000A842EED8206806F0C5FE00F48010B0F508 -:101EC000801F2DD1012522E006F5106000EB4510A2 -:101ED000D0F8009005EBC50104F13C0000EB810057 -:101EE0000079012812D109F00040B0F1004F0DD166 -:101EF000012105EBC50204F13C0000EB8200C1703A -:101F0000E8B240F080012046FFF799FB6D1C606845 -:101F1000A842D9D82068406900F48010216848613F -:101F2000206806F08FFE00F40010B0F5001F44D1C9 -:101F3000012538E006F5306000EB4510D0F8009040 -:101F400005EBC50104F51F7000EB81000079012845 -:101F500028D109F00040B0F1004F23D109F48030BE -:101F600094F8FC1401F0010188421BD1012105EB1A -:101F7000C50204F51F7000EB8200C170DBF8180089 -:101F800040F08000CBF81800DBF8140000F080006F -:101F900040B940F60400805940F4007140F6040056 -:101FA000815103E06D1C6068A842C3D800BF20685F -:101FB000406900F4001021684861206806F042FE84 -:101FC00000F08040B0F1804F08D12046FFF709FBB8 -:101FD0002068406900F0804021684861206806F070 -:101FE00031FE00F0040004280FD12068D0F80490DE -:101FF00009F00400042802D12046FFF719FB2068ED -:10200000406840EA09002168486000BFA9E470B553 -:1020100004460D462946D4F8080505F067FA70BD58 -:1020200070B504460D462946D4F8080505F082FA35 -:1020300070BD70B58AB0044614B901200AB070BDF5 -:10204000266894F8BD0428B9002084F8BC04204612 -:1020500000F0A2F8032084F8BD04F06B00F4807057 -:1020600008B900212161206806F060F9282204F1F6 -:1020700010016846FEF737F994E80F0005F02EFFCF -:1020800020B1022084F8BD040120D7E70021206898 -:1020900006F00DFE002531E0012105EBC50204F13B -:1020A0003C0000EB8200417005EBC50104F13C00EF -:1020B00000F8215005EBC50100EB810005810021EE -:1020C00005EBC50204F13C0000EB8200017105EB59 -:1020D000C50204F13C0000EB8200C16005EBC502C3 -:1020E00004F13C0000EB8200016105EBC50204F144 -:1020F0003C0000EB82008161681CC5B26068A842A8 -:10210000CAD800252AE0002105EBC50204F51F709E -:1021100000EB8200417005EBC50104F51F7000F86B -:102120002150002105EBC50200EB8200017105EB97 -:10213000C50204F51F7000EB8200C16005EBC5020B -:1021400004F51F7000EB8200016105EBC50204F588 -:102150001F7000EB82008161681CC5B26068A842F4 -:10216000D1D8282204F110016846FEF7BCF894E8A3 -:102170000F0005F0EBFF20B1022084F8BD04012020 -:102180005CE7002084F83800012084F8BD04206852 -:1021900005F0CAFF002051E710B586B004461421AF -:1021A00001A8FEF7B9F82068B0F1A04F42D100BFF6 -:1021B000002000902048006840F001001E4908609F -:1021C0000846006800F00100009000BF00BF4FF417 -:1021D000C050019002200290002003900320049040 -:1021E0000A20059001A91548FEF7A6FF00BF124876 -:1021F000001D006840F080000F49091D086000BF05 -:10220000002000900C481430006840F480400A49D7 -:10221000143108600846006800F48040009000BF58 -:1022200000BF00BF002205214320FFF75BF94320D8 -:10223000FFF748F906B010BD3038024000000240F8 -:1022400070B504460125E06808B9002506E0E0689D -:10225000022801D1012501E0FEF7BCFC2946D4F893 -:10226000080505F010FAD4F8080505F0B7F970BDB7 -:1022700010B50446D4F8080505F0E6F910BD10B510 -:102280000446D4F8080505F0EAF910BD70B5044617 -:102290000D4600BF94F8BC04012801D1022070BD96 -:1022A000012084F8BC0400BF84F838502946206817 -:1022B00006F031FD00BF002084F8BC0400BF00BF61 -:1022C000EDE710B5044604F2C441D4F8080505F062 -:1022D000F1F910BD70B50446256800BF94F8BC0440 -:1022E000012801D1022070BD012084F8BC0400BF88 -:1022F000A06A012806D1A069012803D0A86B40F488 -:102300008030A863206806F0EDFB206805F0FAFE37 -:1023100000BF002084F8BC0400BF00BFE3E700005A -:1023200010B50446D4F8080505F021FA2068D0F865 -:10233000000E40F001002168C1F8000E206A28B1AB -:102340000348006840F006000149086010BD000025 -:1023500010ED00E008B50120034908620348006859 -:10236000009000BF08BD000000000E420070004059 -:10237000F8B5044600250026207800F0010020B9B9 -:10238000207800F0040004282FD100205B498866E3 -:10239000FEF7E4FF054606E0FEF7E0FF401B0228DB -:1023A00001D90320F8BD56480068C0F3C06000287A -:1023B000F2D160688101207A41EA0070504984318D -:1023C000086001204D498866FEF7C8FF054606E013 -:1023D000FEF7C4FF401B022801D90320E2E748486A -:1023E0000068C0F3C0600028F2D0207800F002003E -:1023F00002287DD100BF0020009041484030006895 -:1024000040F080503E49403108600846006800F0C6 -:102410008050009000BF00BF3A48006840F48070D0 -:1024200038490860FEF79AFF054606E0FEF796FF7A -:10243000401B022801D90320B4E73248006800F4A9 -:1024400080700028F2D02E487030006800F440768A -:102450004EB3A08900F44070B04224D028487030B8 -:10246000006820F4407601202749086000200860B9 -:10247000234870300660006800F0010098B1FEF754 -:102480006DFF054608E0FEF769FF401B41F2883109 -:10249000884201D9032085E7194870300068C0F3ED -:1024A00040000028EFD000BFA08900F44070B0F5D4 -:1024B000407F0CD112480830006820F4F810134A0D -:1024C000E168114008430E490831086007E00C48F4 -:1024D0000830006820F4F8100949083108600848FD -:1024E00070300068A189C1F30B010843044900E082 -:1024F00002E07031086000BF002053E7000047424F -:102500000038024000700040400E4742FFFCFF0FC1 -:1025100070B504460D460CB9012070BD58480068DE -:1025200000F00700A84209D255490D70084600681E -:1025300000F00700A84201D00120EEE7207800F06B -:10254000020002281DD1207800F00400042805D1E3 -:102550004C48006840F4E0504A490860207800F098 -:102560000800082805D14748006840F46040454904 -:1025700008604448006820F0F000A1680843414921 -:102580000860207800F00100A8B36068012807D136 -:102590003C4808380068C0F34040B8B90120BCE7A7 -:1025A0006068022802D06068032807D135480838DF -:1025B0000068C0F3406048B90120AEE731480838F0 -:1025C0000068C0F3400008B90120A6E72D48006864 -:1025D00020F00300616808432A490860FEF7BEFE48 -:1025E000064609E0FEF7BAFE801B41F288318842B8 -:1025F00002D9032091E707E02248006800F00C00B0 -:102600006168B0EB810FEDD11D48006800F0070054 -:10261000A84209D91A490D700846006800F0070061 -:10262000A84201D0012078E7207800F004000428B7 -:1026300007D11448006820F4E050E16808431149CC -:102640000860207800F00800082808D10D480068CC -:1026500020F46040216940EAC1000A49086000F0A6 -:1026600061F808490968C1F30311074A515CC84081 -:102670000649086006480068FEF7A0FE00204CE707 -:10268000003C02400838024090E70008100000209B -:10269000080000200F2202600D4A126802F00302B7 -:1026A00042600B4A126802F0F0028260084A126827 -:1026B00002F4E052C260064A126802F46042D20894 -:1026C0000261044A126802F007020A6070470000C3 -:1026D00008380240003C0240014800687047000092 -:1026E0001000002000B5FFF7F7FF04490968C1F3A7 -:1026F0008221034A515CC84000BD000008380240F6 -:10270000A0E7000800B5FFF7E7FF04490968C1F337 -:102710004231034A515CC84000BD00000838024005 -:10272000A0E700082DE9F047002400250026A14677 -:102730002548006800F00C0020B1042805D00828C6 -:102740003AD105E0DFF8849039E0DFF8849036E094 -:102750001D48001F006800F03F041B48001F006870 -:1027600000F4800078B11A481749091F0968C1F3BD -:102770008811A0FB01700146224600233846FDF770 -:1027800081FD05460EE011480F49091F0968C1F394 -:102790008811A0FB01700146224600233846FDF750 -:1027A00071FD05460848001F0068C0F30140401C49 -:1027B0004600B5FBF6F902E0DFF8109000BF00BF5D -:1027C0004846BDE8F0870000083802400024F400C5 -:1027D00000127A00F8B504460CB90120F8BD207843 -:1027E00000F00100002874D0F948006800F00C00E7 -:1027F00004280DD0F648006800F00C00082813D11A -:10280000F348001F006800F48000B0F5800F0BD182 -:10281000EF4808380068C0F34040002859D060688D -:10282000002856D10120D9E700BF6068B0F5803F8D -:1028300008D1E7480838006840F48030E449083996 -:1028400008601EE06068B0F5A02F0DD1E0480838A0 -:10285000006840F48020DE490839086008460068B6 -:1028600040F4803008600CE0D9480838006820F453 -:102870008030D749083908600846006820F4802075 -:10288000086000BF606890B1FEF768FD054606E08D -:10289000FEF764FD401B642801D903209EE7CC4865 -:1028A00008380068C0F340400028F1D011E0FEF77E -:1028B00055FD054606E0FEF751FD401B642801D991 -:1028C00003208BE7C24808380068C0F34040002866 -:1028D000F1D1207800F0020002285FD1BC480068E6 -:1028E00000F00C0058B1BA48006800F00C0008284D -:1028F0001CD1B748001F006800F48000B0B9B4488C -:1029000008380068C0F3400020B1E068012801D019 -:10291000012063E7AE480838006820F0F80021691C -:1029200040EAC100AA490839086037E0E06800B30E -:102930000120A8490860FEF711FD054606E0FEF7F4 -:102940000DFD401B022801D9032047E7A0480838A5 -:102950000068C0F340000028F1D09D4808380068A6 -:1029600020F0F800216940EAC1009949083908605F -:1029700014E0002097490860FEF7F0FC054606E0E9 -:10298000FEF7ECFC401B022801D9032026E7904803 -:1029900008380068C0F340000028F1D1207800F02A -:1029A000080008282CD16069A8B101208A49086074 -:1029B000FEF7D4FC054606E0FEF7D0FC401B0228DB -:1029C00001D903200AE782486C300068C0F3400058 -:1029D0000028F1D014E000207F490860FEF7BEFC1B -:1029E000054606E0FEF7BAFC401B022801D9032089 -:1029F000F4E677486C300068C0F340000028F1D15D -:102A0000207800F00400042870D100277048383086 -:102A1000006800F0805090B900BF002000906C4822 -:102A20003830006840F08050694938310860084605 -:102A3000006800F08050009000BF00BF0127674889 -:102A4000006800F48070B0B96448006840F4807099 -:102A500062490860FEF782FC054606E0FEF77EFC50 -:102A6000401B022801D90320B8E65C48006800F446 -:102A700080700028F2D000BFA068012808D1544817 -:102A80006830006840F001005149683108601DE07D -:102A9000A06805280DD14E486830006840F0040059 -:102AA0004B49683108600846006840F00100086042 -:102AB0000CE047486830006820F001004449683164 -:102AC00008600846006820F00400086000BFA068A5 -:102AD000A8B1FEF743FC054609E0FEF73FFC401BAA -:102AE00041F28831884202D9032077E626E038484F -:102AF00068300068C0F340000028EED013E0FEF715 -:102B00002DFC054608E0FEF729FC401B41F2883108 -:102B1000884201D9032061E62D4868300068C0F37F -:102B200040000028EFD1012F07D129483830006834 -:102B300020F0805026493831086000BFA069002885 -:102B400045D02348006800F00C0008285DD0A0693B -:102B5000022845D100201F490866FEF7FFFB054605 -:102B600006E0FEF7FBFB401B022801D9032035E6F7 -:102B7000174808380068C0F340600028F1D1D4E954 -:102B800007010843616A40EA81110122A06AC2EB91 -:102B9000500041EA00412C20005D41EA00600C49F0 -:102BA000091F086001200B490866FEF7D7FB0546A0 -:102BB00006E0FEF7D3FB401B022801D903200DE6F7 -:102BC000034808380068C0F340600028F1D049E0AD -:102BD0000838024000004742800E47420070004023 -:102BE000002021490866FEF7B9FB054606E0FEF71E -:102BF000B5FB401B022801D90320EFE51B48006804 -:102C0000C0F340600028F2D12CE0A069012800D177 -:102C1000E4E51648001D0668A069012820D006F4E6 -:102C20008001E06981421BD106F03F01206A8142A8 -:102C300016D147F6C0703040616AB0EB811F0FD1EA -:102C400006F440310122A06AC2EB5000B1EB004F04 -:102C500006D106F070612C20005DB1EB006F01D051 -:102C60000120BBE50020B9E50000474200380240E2 -:102C700010B50023046804F1500303EB81031A60CC -:102C800010BD000070B505460B46164600242868A6 -:102C900040680E4900EA0104200CD870C4F30420F7 -:102CA000587004F03F009870C4F3423018705EB959 -:102CB000D87801F0D0FED870587801F0CCFE58706A -:102CC000987801F0C8FE9870002070BD3FFFFF00AB -:102CD00070B504460B46164600252068806A586089 -:102CE00020680069C0F30E009860206800680E49F3 -:102CF00000EA0105C5F305401870C5F306205870B9 -:102D000005F07F009870A80DD8705EB9187801F0B2 -:102D1000A2FE1870587801F09EFE5870987801F065 -:102D20009AFE9870002070BD7F7F7F0070B50446CA -:102D300001250CB9012070BD607F20B900202077EB -:102D4000204600F045F80220607700BFCA202168C5 -:102D5000486253202168486200BF204601F094FE7B -:102D60000546EDB9206880681849084021688860E8 -:102D700021696068084361690843216889680843DC -:102D8000216888602168E0680861206801692089FD -:102D900041EA004021680861204601F09AFE05469C -:102DA0006DB92068006C20F48020216808642068D8 -:102DB000006CA1690843216808640120607700BFA6 -:102DC000FF202168486200BF2846B4E7BFFF8FFF9D -:102DD0001FB504460020009001900290039009491D -:102DE000206888420CD102200090C0010390684600 -:102DF000FFF7BEFA08B1FDF7EDFE012002490860B9 -:102E00001FBD0000002800403C0E47422DE9F04164 -:102E100005460C4617464FF0000800BF287F0128E2 -:102E200002D10220BDE8F0810120287700BF0220F6 -:102E300068774FB9607800F01000102804D16078EE -:102E400000F0EF000A30607087B9E07801F00EFE04 -:102E50000304607801F00AFE43EA0023A07801F041 -:102E600005FE0343207843EA403809E0E078000497 -:102E7000617840EA0120A1780843217840EA41388E -:102E800000BFCA202968486253202968486200BFF1 -:102E9000284601F0F9FD064646B90B4808EA00004D -:102EA00029684860284601F014FE06460EB9012044 -:102EB000687700BFFF202968486200BF00BF00207C -:102EC000287700BF3046ADE73FFFFF002DE9F04116 -:102ED00004460D4617464FF0000800BF207F01282A -:102EE00002D10220BDE8F0810120207700BF02203E -:102EF0006077CFB92068806800F0400000B102E040 -:102F00000020E87000BF287801F0B0FD0304687865 -:102F100001F0ACFD43EA0023A87801F0A7FD0343CC -:102F2000E87843EA805812E02068806800F04000AA -:102F300000B102E00020E87000BF28780004697842 -:102F400040EA0120A9780843E97840EA815800BFA7 -:102F5000CA202168486253202168486200BF204689 -:102F600001F092FD0646B6B9124808EA0000216851 -:102F700008602068806820F4802021688860D5E996 -:102F80000301084321688968084321688860204656 -:102F900001F09FFD06460EB90120607700BFFF20BB -:102FA0002168486200BF00BF0020207700BF304684 -:102FB00098E700007F7F7F0070B5044600252068F9 -:102FC000C06820F0A0002168C860FEF7C7F9054678 -:102FD00007E0FEF7C3F9401BB0F57A7F01D9032063 -:102FE00070BD2068C06800F020000028F1D00020EB -:102FF000F6E70000F0B589B004460E46002703202E -:1030000084F83400606C032820D0B6F5805F04D1CA -:10301000A06B40F08050A0631CE0B6F5006F07D1B4 -:10302000204602F0E7FB0546A06B2843A06311E0B1 -:103030003EB9204602F0AAFB0546A06B2843A063D8 -:1030400008E0A06B40F00060A06303E0A06B40F0DC -:103050008050A063A06B38B11748216888630120B5 -:1030600084F83400012713E060680390A06804909E -:10307000E0680590069660690790A069089006A828 -:1030800007C88DE80700206803A90EC901F05DFD9F -:103090004FF40071206801F0C9FD054635B10648BE -:1030A00021688863A06B2843A0630127012084F86E -:1030B0003400384609B0F0BDFF05400070470000FD -:1030C00010B50246506E800F0870506EC0F38360DA -:1030D0004870506EC0F301608870506E000CC8706C -:1030E000B2F86400000A087192F864004871906EAA -:1030F000000DC880906EC0F3034008726820805AAB -:10310000C0F3C03048726820805AC0F380308872A3 -:103110006820805AC0F34030C8726820805AC0F3DB -:103120000030087300204873506C002836D16820A6 -:10313000805A8005030DD06E43EA90700861D06E0E -:10314000C0F3C2600875D06EC0F302604875D06EDF -:10315000C0F342508875D06EC0F38240C875D06EFF -:10316000C0F3C23008760869401C50650B7E506D74 -:1031700003F007039B1C01249C4060435065087AC0 -:1031800000F00F03012098409065D2E915035B0A17 -:103190005843D0654FF40073136621E0506C01284A -:1031A00013D16820805C8006830AD06E43EA104009 -:1031B00008610869401C83025365536DD3654FF461 -:1031C00000739365936D13660AE02E481368986345 -:1031D000906B40F080509063012082F8340010BD65 -:1031E0006C20805AC0F3803001F8190F6C20805A8F -:1031F000C0F3C61048706C20805C00F07F008870BF -:10320000106FC00FC870106FC0F341700871106F5D -:10321000C0F382604871106FC0F383508871106FE3 -:10322000C0F34050C87100200872106FC0F3004016 -:1032300048727020805AC0F3C03088727020805A63 -:10324000C0F38030C8727020805AC0F340300873D9 -:103250007020805AC0F3003048737020805AC0F349 -:10326000812088737020805AC0F30120C8737020B9 -:10327000805CC0F3460008740120487419390020AE -:10328000ADE70000FF0540000246506C0860906CFE -:103290004860D06C8860106DC860506D0861906D9A -:1032A0004861D06D8861106EC86100207047F8B524 -:1032B0000446002000906946204602F04FFA054679 -:1032C00015B1A06B2843A0630098C0F34326304695 -:1032D000F8BD10B504460CB9012010BD94F83400B7 -:1032E00020B900202077204600F06AF8032084F8F7 -:1032F0003400204600F00CF808B10120EDE7002072 -:10330000A0632063012084F834000020E5E700007A -:1033100070B58AB00446002004900590069007908E -:1033200008907620099007A807C88DE80700206854 -:1033300004A90EC901F009FC064616B101200AB025 -:1033400070BD00201C490860206801F018FC0120B5 -:103350001949A039C1F8A0000220FDF7D9FE204686 -:1033600002F096F905463DB1012084F83400A06BC7 -:103370002843A0630120E2E7204602F007F9054652 -:103380003DB1012084F83400A06B2843A0630120E4 -:10339000D5E74FF40071206801F048FC05464DB1B7 -:1033A000064821688863A06B2843A063012084F845 -:1033B0003400C4E70020C2E7A0802542FF0540009A -:1033C00010B586B00446142101A8FCF7A5FF5449A6 -:1033D000206888427ED100BF0020009051480068DC -:1033E00040F400604F4908600846006800F400603F -:1033F000009000BF00BF00BF002000904948143873 -:10340000006840F004004749143908600846006825 -:1034100000F00400009000BF00BF00BF002000903B -:103420000846006840F0080008600846006800F0A0 -:103430000800009000BF00BF4FF4F8500190022038 -:10344000029001200390022004900C20059001A915 -:103450003548FDF771FE0420019002200290012002 -:103460000390022004900C20059001A92F48FDF73D -:1034700063FE2F482F4908604FF00060486000212C -:103480002C488160C1604FF4806101618900416115 -:10349000890081612021C161002101620421416212 -:1034A000032181624FF40001C16289100163FDF7BD -:1034B0006FFD08B1FDF78EFB00BF1E4820648463DA -:1034C00000BF1B4848301C4908604FF0006048604E -:1034D000402100E021E0184881600021C1604FF4E4 -:1034E0008061016189004161890081612021C161A0 -:1034F0000021016204214162032181624FF4000135 -:10350000C16289100163FDF743FD08B1FDF762FB5D -:1035100000BF0948E063846300BF06B010BD00002F -:10352000002C01404438024000080240000C0240D8 -:103530005864024090050020F00500202DE9F0437A -:1035400087B004460F4691461D46C8463FB9A06B5A -:1035500040F00060A063012007B0BDE8F08394F85C -:10356000340001287ED10020A06308EB0501E06D46 -:10357000814205D9A06B40F00070A0630120EBE709 -:10358000032084F8340000202168C8622068C06BE2 -:1035900040F22A3108432168C8633848216CC86367 -:1035A0003748216CC8640020216C08650021206C1C -:1035B0008160206C0068006820F0C000216C896880 -:1035C0000843216C096808606A029308226802F1C6 -:1035D00080013A46206CFDF751FD80B12068C06B38 -:1035E00020F495702168C863264821688863A06B21 -:1035F00040F08040A063012084F83400ACE7012053 -:1036000021490860606C012801D04FEA48284FF03A -:10361000FF300190680202909020039002200490F5 -:10362000002005900120069001A9206801F068FAA9 -:10363000012D07D9822020634146206801F05EFBFE -:10364000064606E0812020634146206801F072FBB7 -:10365000064676B10B4821688863A06B3043A063AF -:10366000012000E007E084F83400002020630120FE -:1036700072E7002070E702206EE70000F1530008B7 -:103680007D530008FF0540008C85254210B5044697 -:10369000FDF766F910BD00002DE9F04387B0044640 -:1036A000884691461D464F46B8F1000F07D1A06BE2 -:1036B00040F00060A063012007B0BDE8F08394F8FB -:1036C0003400012874D10020A0637919E06D814293 -:1036D00005D9A06B40F00070A0630120ECE7032047 -:1036E00084F8340000202168C8622068C06B40F272 -:1036F0001A2108432168C8633848E16BC863384819 -:10370000E16BC8640020E16B0865606C012800D0A3 -:103710007F02012D07D9A02020633946206801F0DF -:10372000E7FB064606E0902020633946206801F05A -:10373000FBFB064666B12B4821688863A06B3043CB -:10374000A063012084F83400002020630120B3E747 -:103750000120254908604021E06B8160E06B006832 -:10376000006820F0C000E16B89680843E16B0968DC -:10377000086069028B08216801F180024146E06B14 -:10378000FDF77CFCA8B12068C06B40F21A21884389 -:103790002168C863134821688863A06B40F08040AB -:1037A000A063012084F8340000202063012083E717 -:1037B00011E04FF0FF3001906802029090200390DA -:1037C0000020049005900120069001A9206801F0D6 -:1037D00097F9002070E702206EE7000039540008D6 -:1037E0007D530008FF0540008C85254210B5044636 -:1037F0000CB9012010BD606A38B96068B0F5827FED -:1038000000D105E00021E16102E000212161616158 -:103810000021A16294F8510028B9002084F85000DA -:10382000204600F047F8022084F851002068006824 -:1038300020F0400021680860A08800F4827021898F -:1038400001F404410843A18901F400610843217C8B -:1038500001F002010843217D01F001010843218BA1 -:1038600001F400710843217F01F038010843202151 -:10387000095D01F080010843218D01F400510843E6 -:10388000216808600421A06901EA104094F824101E -:1038900001F010010843216848602068C06920F4E5 -:1038A00000602168C86100206065012084F8510033 -:1038B00000209FE710B586B00446142101A8FCF74C -:1038C0002BFD1B49206888422FD100BF00200090AB -:1038D0001848006840F4004016490860084600682F -:1038E00000F40040009000BF00BF00BF0020009027 -:1038F00010481038006840F002000E491039086086 -:103900000846006800F00200009000BF00BF3820A9 -:1039100001900220029000200390032004900620D2 -:10392000059001A90448FDF707FC06B010BD000092 -:10393000003C004040380240000402402DE9FF5F97 -:103940000446884691461D460E9E012002900020A6 -:10395000019000BF94F85000012803D1022004B068 -:10396000BDE8F09F012084F8500000BFFDF7F6FC91 -:10397000074694F851B060680390AA46BBF1010F66 -:103980000BD00398B0F5827F04D1A06810B9BBF1C9 -:10399000040F02D002200190DBE0B8F1000F03D049 -:1039A000B9F1000F00D015B901200190D1E094F8D1 -:1039B0005100042802D0052084F8510000206065E1 -:1039C000C4F83890E587A587C4F83080E586A586D9 -:1039D000206460642068006800F04000402805D042 -:1039E0002068006840F0400021680860E068B0F599 -:1039F000006F4AD1606810B1BAF1010F09D1206B94 -:103A000000882168C860206B801C2063E08E401E07 -:103A1000E08633E02068806800F00200022810D1C0 -:103A2000E08E70B1029801280BD1206B00882168CC -:103A3000C860206B801C2063E08E401EE086002062 -:103A400002902068806800F0010068B1E08F58B1F2 -:103A50002068C068A16B0880A06B801CA063E08F09 -:103A6000401EE08701200290FDF778FCC01BB042A9 -:103A700004D3701C10B1032001906AE0E08E00288E -:103A8000C8D1E08F0028C5D14AE0606810B1BAF112 -:103A9000010F09D1206B007821680873206B401C4E -:103AA0002063E08E401EE08634E02068806800F0ED -:103AB0000200022810D1E08E70B1029801280BD1CB -:103AC000206B007821680873206B401C2063E08E17 -:103AD000401EE086002002902068806800F001000F -:103AE00068B1E08F58B12068C068A16B0870A06B06 -:103AF000401CA063E08F401EE08701200290FDF78C -:103B00002DFCC01BB04201D3701C00B916B90320B4 -:103B100001901EE0E08E0028C7D1E08F0028C4D1BC -:103B20003A463146204601F08DFF20B10120019038 -:103B3000202060650DE0A06850B900BF0020009013 -:103B40002068C068009020688068009000BF00BFB7 -:103B500000BF012084F8510000BF002084F850000D -:103B600000BF0198FBE67047704710B504460CB9DA -:103B7000012010BD94F83D0028B9002084F83C00D5 -:103B8000204600F025F8022084F83D00211D206821 -:103B900002F092F8012084F8460000BF84F83E004D -:103BA00001213F200155402001554120015500BF12 -:103BB00000BF012084F842004320015544200155F4 -:103BC0004520015500BF012084F83D000020D0E7CA -:103BD00070470000014691F83D00012801D0012006 -:103BE0007047022081F83D000868C06840F001007D -:103BF0000B68D8601A4B086898421BD00868B0F16F -:103C0000804F17D0174B0868984213D0164B08689E -:103C100098420FD0154B086898420BD0144B086897 -:103C2000984207D0134B0868984203D0124B08689B -:103C300098420CD10868806800F00702062A0CD070 -:103C40000868006840F001000B68186005E008682B -:103C5000006840F001000B6818600020C0E7000019 -:103C6000000001400004004000080040000C00403B -:103C7000000401400040014000180040704710B5AA -:103C8000044620680069C0F34000D8B12068C068CD -:103C9000C0F34000B0B16FF002002168086101205C -:103CA00020772068806900F0030018B12046FFF7F4 -:103CB000E5FF05E0204600F0ADF8204600F0ABF847 -:103CC0000020207720680069C0F38000D8B1206808 -:103CD000C068C0F38000B0B16FF0040021680861D3 -:103CE000022020772068806900F4407018B12046D7 -:103CF000FFF7C4FF05E0204600F08CF8204600F0F6 -:103D00008AF80020207720680069C0F3C000D8B18D -:103D10002068C068C0F3C000B0B16FF0080021682F -:103D20000861042020772068C06900F0030018B102 -:103D30002046FFF7A3FF05E0204600F06BF8204681 -:103D400000F069F80020207720680069C0F30010B7 -:103D5000D8B12068C068C0F30010B0B16FF0100097 -:103D600021680861082020772068C06900F440704D -:103D700018B12046FFF782FF05E0204600F04AF820 -:103D8000204600F048F8002020772068006900F005 -:103D9000010058B12068C06800F0010030B16FF038 -:103DA000010021680861204600F036F820680069AB -:103DB000C0F3C01058B12068C068C0F3C01030B163 -:103DC0006FF08000216808612046FFF7CCFE206874 -:103DD0000069C0F3801058B12068C068C0F380103B -:103DE00030B16FF0400021680861204600F020F8F3 -:103DF00020680069C0F3401058B12068C068C0F363 -:103E0000401030B16FF02000216808612046FFF7B4 -:103E1000ABFE10BD7047704710B5044603492068DB -:103E2000884201D1FDF7A0FA10BD0000001000404B -:103E300070477047704700002DE9F84F044620682E -:103E400005682068C668206847694FF00009CA46BF -:103E500005F00F09B9F1000F0AD105F0200038B1C3 -:103E600006F0200020B1204602F085F8BDE8F88F6A -:103E7000B9F1000F7CD007F0010018B906F490707A -:103E8000002875D005F0010030B106F4807018B13B -:103E9000206C40F00100206405F0040030B107F010 -:103EA000010018B1206C40F00200206405F002000F -:103EB00030B107F0010018B1206C40F0040020641C -:103EC00005F0080048B106F0200010B907F0010025 -:103ED00018B1206C40F008002064206C002846D007 -:103EE00005F0200028B106F0200010B1204602F0B5 -:103EF00042F820684069C0F3801A206C00F0080086 -:103F000010B9BAF1000F2DD0204601F0DBFF206878 -:103F1000406900F04000402820D100BF00BF216868 -:103F2000143151E8001F21F040002168143141E8AC -:103F30000002002AF3D100BFA06B50B17548A16BFD -:103F40000865A06BFCF7ECFE88B1A06B016D88479B -:103F50000DE02046FFF76EFF09E009E02046FFF77D -:103F600069FF04E02046FFF765FF002020647DE73D -:103F7000206B012876D105F01000002872D006F0E1 -:103F800010000028FAD000BF0020009020680068D0 -:103F9000009020684068009000BF00BF2068406922 -:103FA00000F0400040285ED1A06B006840681FFA16 -:103FB00080F8B8F1000F54D0A08D404551DDA4F831 -:103FC0002E80A06BC069B0F5807F43D000BF00BFDA -:103FD00021680C3151E8001F21F4807021680C31F8 -:103FE00041E80002002AF3D100BF00BF00BF2168F2 -:103FF000143151E8001F21F001002168143141E81B -:104000000002002AF3D100BF00BF00BF21681431B5 -:1040100051E8001F21F040002168143141E80002FE -:10402000002AF3D100BF202084F83E000020206346 -:1040300000BF00BF21680C3151E8001F21F01000C3 -:1040400021680C3141E80002002AF3D100BFA06BC7 -:10405000FCF710FEA08DE28D801A81B22046FFF79A -:10406000E8FE03E740E0A08DE18D401A1FFA80F8DA -:10407000E08DC0B3B8F1000F35D000BF00BF21689C -:104080000C3151E8001F21F4907021680C3141E897 -:104090000002002AF3D100BF00BF00BF2168143125 -:1040A00051E8001F21F001002168143141E80002AD -:1040B000002AF3D100BF202084F83E0000202063B6 -:1040C00000BF00BF21680C3151E8001F21F0100033 -:1040D00021680C3141E80002002AF3D100BF4146BB -:1040E0002046FFF7A6FEC1E605F0800030B106F0DD -:1040F000800018B1204602F039F9B7E605F040001B -:1041000030B106F0400018B1204601F011FFADE6D5 -:1041100000BFABE6915D000810B504460CB9012064 -:1041200010BDA06900B100E000BF94F83D0028B9BF -:10413000002084F83C00204600F028F8242084F871 -:104140003D002068C06820F400502168C860204607 -:1041500001F08EFF2068006920F49040216808611A -:104160002068406920F02A00216848612068C06802 -:1041700040F400502168C86000202064202084F8AA -:104180003D0084F83E000020CAE7000010B586B06C -:104190000446142101A8FCF7BFF83D492068884275 -:1041A00074D100BF002000903A48006840F0100031 -:1041B000384908600846006800F01000009000BF11 -:1041C00000BF00BF0020009032481438006840F063 -:1041D00001003049143908600846006800F0010009 -:1041E000009000BF00BF4FF4C06001900220029019 -:1041F00000200390032004900720059001A9264881 -:10420000FCF79AFF2548264908604FF00060486097 -:10421000002123488160C1604FF480610161002169 -:1042200041618161C16101624162FCF7B1FE08B187 -:10423000FCF7D0FC00BF1A48A063846300BF174896 -:104240007830184908604FF00060486040211548F8 -:1042500081600021C1604FF48061016100214161F2 -:104260008161C16101624162FCF792FE08B1FCF715 -:10427000B1FC00BF0B486063846300BF00220521CE -:104280002520FDF72FF92520FDF71CF906B010BDFC -:1042900000100140443802400000024040640240E7 -:1042A000EC0600204C07002070B504460D4616466B -:1042B00094F83E00202816D105B10EB9012070BD3A -:1042C00000BF94F83C00012801D10220F7E701204B -:1042D00084F83C0000BF0020206332462946204677 -:1042E00001F0DCFFEBE70220E9E7704770472DE9BA -:1042F000F84F04460E46174699464FF0000A94F8C8 -:104300003D0020285AD106B117B90120BDE8F88F29 -:1043100000BF94F83C00012801D10220F6E70120FB -:1043200084F83C0000BF00202064212084F83D0078 -:10433000FDF714F88246A784E784A068B0F5805F93 -:1043400004D1206910B90025B04602E035464FF08F -:10435000000800BF002084F83C0000BF1BE053466B -:10436000002280212046CDF8009002F02FF808B1FD -:104370000320CBE745B9B8F80000C0F30800216876 -:10438000486008F1020803E02878216848606D1C45 -:10439000E08C401EE084E08C0028E0D153460022EF -:1043A00040212046CDF8009002F010F808B103201B -:1043B000ACE7202084F83D000020A7E70220A5E715 -:1043C000704700BFFEE730B50B46002100BF16E086 -:1043D0000A24B4EB107F05D9302404EB107403F8E1 -:1043E000114005E0412404EB10740A3C03F811402D -:1043F000000100254C00641C1D554C1CE1B291428B -:10440000E6DB30BD08B500BF00200090164800680C -:1044100040F48000144908600846006800F48000F9 -:10442000009000BF00BF002205213A20FDF75AF896 -:104430003A20FDF747F800220F213B20FDF752F804 -:104440003B20FDF73FF800220F214520FDF74AF8F9 -:104450004520FDF737F8002205214620FDF742F8F8 -:104460004620FDF72FF808BD3038024010B503494B -:104470000348FCF7B2FB0349087010BDAD000020F3 -:1044800010E80008AC00002000B587B01C220649E7 -:104490006846FBF728FF0021684606F067FB0349E2 -:1044A000086007B000BD00006CE7000800000020B5 -:1044B00000B587B0142102A8FBF72EFF00BF002033 -:1044C00001907F48006840F010007D490860084670 -:1044D000006800F01000019000BF00BF00BF002086 -:1044E00001900846006840F0040008600846006833 -:1044F00000F00400019000BF00BF00BF0020019049 -:104500000846006840F0200008600846006800F097 -:104510002000019000BF00BF00BF002001900846AE -:10452000006840F0800008600846006800F08000E5 -:10453000019000BF00BF00BF002001900846006846 -:1045400040F0010008600846006800F0010001909A -:1045500000BF00BF00BF002001900846006840F087 -:10456000020008600846006800F00200019000BFE9 -:1045700000BF00BF002001900846006840F04000E6 -:1045800008600846006800F04000019000BF00BFCE -:1045900000BF002001900846006840F00800086055 -:1045A0000846006800F00800019000BF00BF00222C -:1045B0004FF400514348FCF7CBFE00224FF4C051AA -:1045C0004148FCF7C5FE4FF6FF70029003200390B0 -:1045D0000020049002A93D48FCF7AEFD4FF40050C6 -:1045E00002900120039000200490059002A9354814 -:1045F000FCF7A2FD4FF6FF7002900320039000200D -:10460000049002A93248FCF797FDFF200290032096 -:1046100003900020049002A92A48FCF78DFD48F27F -:10462000FF100290032003900020049002A9294863 -:10463000FCF782FD4FF6C730029003200390002064 -:10464000049002A92448FCF777FD4FF6FF70029012 -:10465000032003900020049002A92048FCF76CFD81 -:104660004FF48060029000200390049002A91A4841 -:10467000FCF762FD4CF2FB700290032003900020D7 -:10468000049002A91048FCF757FD4FF4C050029067 -:104690000120039000200490059002A90A48FCF72D -:1046A0004BFD4FF4005002904FF48810039000200F -:1046B000049002A90448FCF73FFD07B000BD0000CC -:1046C0003038024000080240000C02400010024056 -:1046D00000140240000002400004024000180240A2 -:1046E00010B50A480A490860002048607F21084840 -:1046F0008160FF21C1600021016141618161FEF79C -:1047000015FB08B1FCF766FA10BD00000028004058 -:10471000EC0400207047000010B50E480E490860F8 -:104720004FF48270486000210B488160C1600161D4 -:1047300041614FF4007181610021C16101624162F8 -:1047400081620A21C162FFF751F808B1FCF742FA11 -:1047500010BD0000003C00405006002010B50B4882 -:104760000B4908604FF4E13048600021084881603F -:10477000C16001610C21416100218161C161FFF7CC -:10478000CBFC08B1FCF726FA10BD00000010014078 -:10479000A806002010B500220D490E4802F0EFFCDB -:1047A00008B1FCF717FA0C490A4803F01DF808B1E4 -:1047B000FCF710FA0949074802F0F0F808B1FCF7D5 -:1047C00009FA044803F012F908B1FCF703FA10BD26 -:1047D0003001002090F50020A4010020800100207D -:1047E00000BFFEE700BFFEE710B50248FDF7AAF8DC -:1047F00010BD00006C0A01202DE9F04704460D466B -:1048000026683746D6F8408007F5306000EB451043 -:10481000D0F80890104880450BD909F40040B0F555 -:10482000004F06D14FF4004107F5306000EB451012 -:1048300081602046FDF745FD0748804508D920697D -:10484000012805D104F2C4420121206803F064FE6E -:104850000020BDE8F08700000A30544F2DE9F047F2 -:1048600005460C46D5F800904E46D9F840A006F50E -:10487000306000EB4410D0F808802869012855D139 -:1048800008F0080008280FD1434882450BD908F4E6 -:104890000040B0F5004F7BD14FF4004106F5306089 -:1048A00000EB4410816073E008F02000202806D15E -:1048B000202106F5306000EB4410816068E008F0CC -:1048C0002800002864D1344882450CD908F40040FF -:1048D000B0F5004F07D14FF4004106F5306000EB12 -:1048E0004410816054E004EBC40105F51F7000EB37 -:1048F000810706F5306000EB4410F9690069C0F3E8 -:104900001200081A386264B9B86930B905F2C442B5 -:104910000121286803F000FE03E0396A3869084481 -:104920003861E1B22846FCF773FE31E01B4882454E -:104930001BD108F40040B0F5004F07D14FF40041FF -:1049400006F5306000EB4410816021E008F02000A3 -:10495000202805D1202106F5306000EB441081604D -:10496000E1B22846FCF754FE12E06CB904EBC40136 -:1049700005F51F7000EB8100806928B905F2C4427B -:104980000021286803F0C8FDE1B22846FCF740FE8C -:104990000020BDE8F08700000A30544F0A31544F20 -:1049A0002DE9F84F07460E46D7F80090C84606EBAB -:1049B000C60107F13C0000EB8104A169206A88422E -:1049C00002D90120BDE8F88F216AA069451AE06884 -:1049D000A84200D2E568E81C4FEA900A17E0216A75 -:1049E000A069451AE068A84200D2E568E81C4FEAD1 -:1049F000900A387CABB2F2B200904846216904F0CC -:104A00001DFA206928442061206A2844206208F5A4 -:104A1000106000EB4610806980B2504506D3A16952 -:104A2000206A884202D2A0690028D8D1216AA069F0 -:104A300088420ED806F00F01012000FA01FB40F673 -:104A4000340050F8080020EA0B0040F6340141F829 -:104A500008000020B6E7014600BF080900EB80000F -:104A6000420001F00F001044C0B27047014600221E -:104A700004E0501CC2B2A1F10A00C1B20A29F8D266 -:104A8000100741EA1060704770B504460026002503 -:104A90002068C06800F04000C8B92068C06840F0D5 -:104AA00080002168C860FCF759FC064608E0FCF766 -:104AB00055FC801BB0F57A7F02D904206077012570 -:104AC0002068C06800F0400008B9012DEFD12846E9 -:104AD00070BD70B5044600252068C06820F08000D5 -:104AE0002168C8602068806800F0200030B9204646 -:104AF000FEF762FA10B1042060770125284670BDE8 -:104B000010B5024600230868506248689062D1E9F7 -:104B1000020420430C6920434C6920430343D06ABC -:104B200020F0F7001843D062002010BD014608694C -:104B3000C0B270470146086800F0030070470246A3 -:104B400002F114004318186870470FB410B50446FA -:104B50000021DDE903021043059A1043069A104331 -:104B6000079A1043089A10430143606847F6FF62B2 -:104B7000904308436060002010BC5DF814FB0146C0 -:104B800003200860002070470146D1F8800070477C -:104B900010B50246002308689060D1E90104204363 -:104BA000CC6820430C6920430343D0686FF30B00AB -:104BB0001843D060002010BD70B585B005460C4686 -:104BC00000943720019040200290002003904FF481 -:104BD0008060049069462846FFF7DAFF41F2883288 -:104BE0003721284600F0DCF90646304605B070BD96 -:104BF00070B585B005460C460B482043009029202F -:104C0000019040200290002003904FF480600490B7 -:104C100069462846FFF7BCFF284600F0C9FA064659 -:104C2000304605B070BD00000000108070B585B042 -:104C300005460C4600941020019040200290002070 -:104C400003904FF48060049069462846FFF7A0FF68 -:104C500041F288321021284600F0A2F9064630467B -:104C600005B070BD70B585B005460C4600940620B1 -:104C7000019040200290002003904FF48060049047 -:104C800069462846FFF784FF41F28832062128460C -:104C900000F086F90646304605B070BD30B585B0E7 -:104CA0000446002000900190029003904FF4806031 -:104CB000049069462046FFF76BFF204600F050F94C -:104CC0000546284605B030BD30B585B004464FF4E2 -:104CD000D5700090082001904020029000200390A1 -:104CE0004FF48060049069462046FFF751FF20464C -:104CF00000F0E6FA0546284605B030BD70B585B02F -:104D000005460C460094122001904020029000209D -:104D100003904FF48060049069462846FFF738FFFF -:104D200041F288321221284600F03AF90646304610 -:104D300005B070BD70B585B005460C4600941120D5 -:104D4000019040200290002003904FF48060049076 -:104D500069462846FFF71CFF41F288321121284698 -:104D600000F01EF90646304605B070BDF0B585B0BE -:104D7000064614461D4600940720019040200290EC -:104D8000002003904FF48060049069463046FFF79E -:104D9000FFFE41F288320721304600F001F9074654 -:104DA000384605B0F0BD30B585B00446002000900F -:104DB00002200190C0200290002003904FF48060F8 -:104DC000049069462046FFF7E3FE204600F0BEF956 -:104DD0000546284605B030BD70B585B005460C4681 -:104DE000009409200190C0200290002003904FF40D -:104DF0008060049069462846FFF7CAFE284600F006 -:104E0000A5F90646304605B070BD30B585B00446FC -:104E10000020009033200190402002900020039059 -:104E20004FF48060049069462046FFF7B1FE41F2DE -:104E300088323321204600F0B3F80546284605B0F5 -:104E400030BD70B585B005460C4600940D2001902C -:104E500040200290002003904FF480600490694647 -:104E60002846FFF795FE41F288320D21284600F0D2 -:104E700097F80646304605B070BD70B585B005465A -:104E80000C4600200090032001904020029000205A -:104E900003904FF48060049069462846FFF778FE3F -:104EA00022460321284600F0AFF90646304605B0F9 -:104EB00070BD000030B585B00446002000900C2085 -:104EC000019040200290002003904FF480600490F5 -:104ED00069462046FFF75CFE044A0C21204600F09C -:104EE0005FF80546284605B030BD000000E1F50535 -:104EF00070B585B005460C460094192001904020FD -:104F00000290002003904FF4806004906946284688 -:104F1000FFF73EFE41F288321921284600F040F8A2 -:104F20000646304605B070BD70B585B005460C46E6 -:104F300000941820019040200290002003904FF42C -:104F40008060049069462846FFF722FE41F28832CD -:104F50001821284600F024F80646304605B070BDFA -:104F600001460E480068C0084FF47A73B0FBF3F0B6 -:104F700041F2883300FB03F200BF101EA2F10102D0 -:104F800002D14FF000407047486B00F080000028CD -:104F9000F3D0C52088630020F5E700001000002052 -:104FA0002DE9F04305460F46904666480068C00864 -:104FB0004FF47A71B0FBF1F000FB08F900BFB9F1D2 -:104FC0000000A9F1010903D14FF00040BDE8F083D2 -:104FD0006E6B06F045000028F1D006F40060002852 -:104FE000EDD1686B00F0040010B10420A863EDE778 -:104FF000686B00F0010010B10120A863E6E7C5204E -:10500000A8632846FFF792FDB84201D00120DDE7F2 -:1050100000212846FFF793FD04464B48204008B97D -:105020000020D3E704F00040B0F1004F02D14FF070 -:105030000070CBE704F08040B0F1804F01D14020F8 -:10504000C4E704F00050B0F1005F01D18020BDE75B -:1050500004F08050B0F1805F02D14FF48070B5E76A -:1050600004F00060B0F1006F02D14FF40070ADE7C2 -:1050700004F08060B0F1806F02D14FF48060A5E74A -:1050800004F08070B0F1807F02D14FF400609DE7A2 -:1050900004F40000B0F5000F02D14FF4805095E702 -:1050A00004F48000B0F5800F02D14FF400508DE77A -:1050B00004F40010B0F5001F02D14FF4804085E7E2 -:1050C00004F48010B0F5801F02D14FF400407DE75A -:1050D00004F48020B0F5802F02D14FF4003075E742 -:1050E00004F40030B0F5003F02D14FF480206DE7AA -:1050F00004F48030B0F5803F02D14FF4002065E722 -:1051000004F40040B0F5004F02D14FF480105DE789 -:1051100004F48040B0F5804F02D14FF4001055E701 -:1051200004F40050B0F5005F02D14FF480004DE769 -:1051300004F00800082801D1000547E74FF480304B -:1051400044E700001000002008E0FFFD10B5014614 -:1051500016480068C0084FF47A74B0FBF4F041F2CE -:10516000883400FB04F300BF181EA3F1010302D131 -:105170004FF0004010BD4A6B02F045000028F3D00C -:1051800002F400600028EFD1486B00F0040010B179 -:1051900004208863EEE7486B00F0010010B10120A5 -:1051A0008863E7E7C52088630020E3E7100000205C -:1051B00010B5014613480068C0084FF47A74B0FB7C -:1051C000F4F041F2883400FB04F300BF181EA3F191 -:1051D000010302D14FF0004010BD4A6B02F04500C0 -:1051E0000028F3D002F400600028EFD1486B00F0F3 -:1051F000040010B104208863EEE7C5208863002016 -:10520000EAE70000100000202DE9F04304460F46B5 -:1052100090462A480068C0084FF47A71B0FBF1F05C -:1052200041F2883100FB01F900BFB9F10000A9F19A -:10523000010903D14FF00040BDE8F083666B06F032 -:1052400045000028F1D006F400600028EDD1606B25 -:1052500000F0040010B10420A063EDE7606B00F0E3 -:10526000010010B10120A063E6E72046FFF75EFCD5 -:10527000B84201D00120DFE7C520A063002120460D -:10528000FFF75DFC054605F4604020B9280CA8F83E -:1052900000000020D0E705F48040B0F5804F02D137 -:1052A0004FF40050C8E705F40040B0F5004F02D1BC -:1052B0004FF48050C0E74FF48030BDE7100000206D -:1052C00010B5014618480068C0084FF47A74B0FB66 -:1052D000F4F041F2883400FB04F300BF181EA3F180 -:1052E000010302D14FF0004010BD4A6B02F04500AF -:1052F0000028F3D002F400600028EFD1486B00F0E2 -:10530000040010B104208863EEE7486B00F0010050 -:1053100010B101208863E7E7486B00F0400008B156 -:10532000402088630020DFE71000002010B504460D -:10533000012007490870FBF7CFFA28B90448007824 -:1053400020F00100024908700148007810BD0000FB -:10535000A400002070B5044605F06CFB054604E08F -:10536000FBF7BAFA08B9002070BD05F063FB401BDB -:10537000A042F5D34FF0FF30F6E700002DE9F041F1 -:105380000646B46B3046FBF7DFFC02282CD0206CBD -:10539000476DE06BD0F85480012F02D0B8F1010FB7 -:1053A0001FD11248216888632068C06B20F49D706B -:1053B0002168C863A06B40F08040A0632046FDF7E1 -:1053C00076FF0546062D01D0052D05D12068FFF793 -:1053D00071FDA16B0843A063012084F83400002014 -:1053E00020632046FDF76AFEBDE8F081FF0540001E -:1053F00070B50646B46B206B82280AD12068FFF78F -:1054000059FD05462DB1A06B2843A0632046FDF74A -:1054100055FE2068C06A20F008002168C86240F28A -:105420003A5021688863012084F83400002020630A -:105430002046FEF72BF970BD0146886B0268D26BDF -:1054400042F480720368DA6370472DE9F04389B053 -:1054500004460F46FBF782FF81464FF0000800200C -:10546000019002903E4608212068FFF7DFFB0546C9 -:105470001DB1284609B0BDE8F0835022125B11042B -:105480002068FFF799FB05460DB12846F2E74FF07B -:10549000FF300390082004903020059002200690F1 -:1054A000002007900120089003A92068FFF728FB3F -:1054B0002068FFF7AAFC05460DB12846DAE71CE094 -:1054C0002068406B00F4001040B12068FFF75CFBDF -:1054D00001A941F8280008F1010805E02068406BA7 -:1054E00000F4005000B90EE0FBF738FFA0EB090014 -:1054F000401C10B94FF00040BCE72068406B00F042 -:105500002A000028DCD000BF2068406B00F00800B3 -:1055100018B1082021688863ACE72068406B00F070 -:10552000020018B1022021688863A3E72068406B5D -:1055300000F0200018B12020216888639AE740F22B -:105540003A502168886302980006029901F47F416D -:1055500040EA0120029901F47F0140EA11200299FA -:1055600040EA11603060361D01980006019901F48F -:105570007F4140EA0120019901F47F0140EA1120B6 -:10558000019940EA11603060002073E730B58FB0B8 -:105590000446012003902068FFF7CCFA18B94FF0B9 -:1055A00080600FB030BD606C03281BD02068FFF70F -:1055B000FAFB05460DB12846F3E700212068FFF706 -:1055C000BEFA606704212068FFF7B9FAA0670821D6 -:1055D0002068FFF7B4FAE0670C212068FFF7AFFA04 -:1055E00080210851606C032807D003A92068FFF7C9 -:1055F00044FC05460DB12846D3E7606C032820D053 -:10560000BDF80C1021655022125B11042068FFF7D1 -:10561000E3FB05460DB12846C3E700212068FFF7EC -:105620008EFA606604212068FFF789FAA0660821D7 -:105630002068FFF784FAE0660C212068FFF77FFA04 -:10564000206704212068FFF77AFA010DE16404A9BC -:105650002046FDF735FD10B14FF08050A1E75020F6 -:10566000005B01040A4600232068FFF77FFB054624 -:105670000DB1284695E7D4E90412A069CDE90012DE -:10568000029094E80F00FFF760FA002089E700001D -:10569000F8B5044600200090002600272068FFF798 -:1056A000FDFA05460DB12846F8BD2068FFF70CFB52 -:1056B000054645B10021A1642068FFF7EFFA0546D1 -:1056C0001DB12846F0E70121A164A06C012808D192 -:1056D00000212068FFF770FA054615B14FF08050A1 -:1056E000E2E71DE000212068FFF766FA05460DB1EC -:1056F0002846D9E718492068FFF77AFA054615B118 -:105700004FF08050D0E700212068FFF718FA0646D6 -:10571000012080EAD67080F001070098401C0090BC -:105720004FF6FF710098884201D2002FDAD04FF671 -:10573000FF710098884202D34FF08070B4E706F002 -:105740008040B0F1804F02D10120606401E0002070 -:1057500060640020A8E70000000010C170B5044696 -:105760000D4615B94FF0006070BD5022125B110458 -:105770002068FFF766FB06460EB13046F4E70021CD -:105780002068FFF7DCF928600020EDE77CB50446CF -:1057900000200090019000212068FFF7D0F900F070 -:1057A0000070B0F1007F02D14FF400607CBD69460B -:1057B0002046FFF74AFE05460DB12846F6E7019858 -:1057C00000F4803098B15022125B11042068FFF77A -:1057D000F3F905460DB12846E8E700212068FFF7F8 -:1057E00041FA05460DB12846E0E70020DEE74FF01C -:1057F0008060DBE77CB5044600200090019000212A -:105800002068FFF79CF900F00070B0F1007F02D132 -:105810004FF400607CBD69462046FFF716FE054642 -:105820000DB12846F6E7019800F4802098B1502287 -:10583000125B11042068FFF7BFF905460DB1284639 -:10584000E8E702212068FFF70DFA05460DB128466A -:10585000E0E70020DEE74FF08060DBE71FB504469D -:1058600001201649087005F0D7F810B3FBF740F88F -:1058700020B92046FFF75AFD104908700F480078FC -:10588000012816D00E48006850B90E4B0FCB8DE89A -:105890000F000021684605F0D7F80949086000BFED -:1058A0000748006828B90548007840F0010003491E -:1058B00008700248007804B010BD0000A400002069 -:1058C000A800002024E80008F0B589B007460D467E -:1058D000144601261648007800F0010010B103209C -:1058E00009B0F0BD35B1012D06D0022D0BD0032D2E -:1058F00018D10FE0002617E001A8FAF7E3FF079898 -:105900002060002610E001A8FAF7DCFF089820804C -:10591000002609E001A8FAF7D5FF0898400A2060A0 -:10592000002601E0042600BF00BF3046D8E7000093 -:10593000A40000202DE9F04786B082460E461746A7 -:1059400098464FF0010947F23050FFF703FD002859 -:1059500003DA484606B0BDE8F0874246394630468D -:10596000FAF7EAFF044614BB47F2305211480168C7 -:10597000684605F07DF89DE8070003AB07C3039870 -:10598000102814D10498012811D105F053F80546C8 -:1059900005E0FAF7A1FF10B94FF0000906E005F0A5 -:1059A00049F8401B47F230518842F2D300BF4846C5 -:1059B000D0E70000A800002010B504462046FFF7FD -:1059C000B5FC10BD2DE9F04387B081460D46164663 -:1059D0001F464FF0010847F23050FFF7BBFC00288C -:1059E00003DA404607B0BDE8F0833A463146284620 -:1059F000FAF7C0FF10BB47F230521148016801A806 -:105A000005F036F801A807C804AB07C304981028AE -:105A100014D10598022811D105F00CF8044605E0D0 -:105A2000FAF75AFF10B94FF0000806E005F002F847 -:105A3000001B47F230518842F2D300BF4046D1E705 -:105A4000A80000207CB504460D461646164800689E -:105A50001821B0FBF1F01549B0FBF1F04FF47A7169 -:105A6000484301906068B0F5827F0DD12B4600223B -:105A700080212046009600F01BF898B1606D40F040 -:105A80002000606503207CBD00BF019800B908E0DC -:105A90000198401E019020688068C0F3C010002863 -:105AA000F3D100BF0020EEE71000002040420F00BD -:105AB0002DE9F84F04460D4690461E46DDF8289025 -:105AC000FBF74CFCA0EB0900371AFBF747FC8246BA -:105AD0002C480068C0F3CB307843009045E0701C40 -:105AE000002842D0FBF73AFCA0EB0A00B84200D2F3 -:105AF000A7BB2068406820F0E0002168486060682B -:105B0000B0F5827F0DD1A068B0F5004F03D0A0683A -:105B1000B0F5806F05D12068006820F04000216852 -:105B20000860A06AB0F5005F0DD100BF2068006872 -:105B300020F40050216808602068006840F400509C -:105B40002168086000BF012084F8510000BF0020D8 -:105B500084F8500000BF0320BDE8F88FFFE70098ED -:105B600000B900270098401E0090206880682840F7 -:105B7000A84201D1012000E000204045AFD1002023 -:105B8000EAE700001000002030B501460A4613780D -:105B9000521C147843EA042030BDFEF7FBFD00BF21 -:105BA000012004F02DFFFBE710B500BF502080F36B -:105BB0001188BFF34F8FBFF36F8F00BF08F0A4FBB6 -:105BC00018B14FF080500449086000BF002080F3F6 -:105BD000118800BF10BD000004ED00E000B593B0D7 -:105BE000302107A8FAF798FB142102A8FAF794FBD2 -:105BF00000BF002001902548006840F080502349F4 -:105C000008600846006800F08050019000BF00BFA7 -:105C100000BF002001901E48006840F480401C49ED -:105C200008600846006800F48040019000BF00BF93 -:105C3000052007904FF48030089001200990022041 -:105C40000D9041050E9104210F91A8211091022180 -:105C500011910721129107A8FCF7BCFD08B1FAF7D2 -:105C6000B9FF0F20029002200390002004904FF40F -:105C7000A05005904FF480500690052102A8FCF733 -:105C800047FC08B1FAF7A6FF13B000BD4038024048 -:105C9000007000400348006840F47000014908604B -:105CA0007047000088ED00E010B50248FDF7E7FFFF -:105CB00010BD0000AC07002010B50268294B9842C7 -:105CC0000ED0B0F1804F0BD0274B984208D0274B15 -:105CD000984205D0264B984202D0264B984203D1D9 -:105CE00022F070024B681A431E4B984220D0B0F14C -:105CF000804F1DD01C4B98421AD01C4B984217D095 -:105D00001B4B984214D01B4B984211D01A4B98420F -:105D10000ED01A4B98420BD0194B984208D0194B11 -:105D2000984205D0184B984202D0184B984203D1A4 -:105D300022F44072CB681A4322F080034C6943EA94 -:105D4000040202608B68C3620B688362054B984251 -:105D500002D0084B984201D10B69036301234361D0 -:105D600010BD000000000140000400400008004099 -:105D7000000C00400004014000400140004401408C -:105D80000048014000180040001C00400020004076 -:105D900070B50546AC6B0020E085E0842046FEF738 -:105DA00049F870BD70B506460025B46B206840699F -:105DB000C0F3C01594F83D00212805D125B100207D -:105DC000E084204600F0C4F820684069C0F38015E4 -:105DD00094F83E00222805D125B10020E085204618 -:105DE00000F070F8206C40F0100020642046FEF7B0 -:105DF00021F870BD70B50546AC6B2868006800F4EA -:105E00008070002842D1E08500BF00BF21680C31BE -:105E100051E8001F21F4807021680C3141E8000234 -:105E2000002AF3D100BF00BF00BF2168143151E840 -:105E3000001F21F001002168143141E80002002A0E -:105E4000F3D100BF00BF00BF2168143151E8001F2B -:105E500021F040002168143141E80002002AF3D10A -:105E600000BF202084F83E00206B01280ED100BF27 -:105E700000BF21680C3151E8001F21F0100021689B -:105E80000C3141E80002002AF3D100BF206B012849 -:105E900004D1A18D2046FDF7CCFF02E02046FEF79D -:105EA00024FA70BD70B50546AC6B206B012805D196 -:105EB000A08D41082046FDF7BCFF02E02046FEF71A -:105EC00015FA70BD00BF00BF02680C3252E8002F07 -:105ED00022F4907102680C3242E80013002BF3D1D7 -:105EE00000BF00BF00BF0268143252E8002F22F04A -:105EF00001010268143242E80013002BF3D100BF05 -:105F0000016B01290ED100BF00BF02680C3252E8BC -:105F1000002F22F0100102680C3242E80013002B1F -:105F2000F3D100BF202180F83E10002101637047AB -:105F300010B504462068C06820F040002168C860A1 -:105F4000202084F83D002046FEF73AFA002010BDDC -:105F500000BF00BF02680C3252E8002F22F0C001DF -:105F600002680C3242E80013002BF3D100BF20215D -:105F700080F83D107047F8B5044694F83E0022289A -:105F800073D1A068B0F5805F0CD1206950B90025AD -:105F9000A66A20684068C0F308003080A06A801CB0 -:105FA000A06215E0A56A0026A068B0F5805F03D066 -:105FB000A06828B9206918B920684068287004E0F2 -:105FC0002068406800F07F002870A06A401CA06232 -:105FD000E08D401E80B2E085002844D12068C06872 -:105FE00020F020002168C8602068C06820F480701C -:105FF0002168C8602068406920F00100216848617C -:10600000202084F83E00206B012826D10020206348 -:1060100000BF00BF21680C3151E8001F21F01000C3 -:1060200021680C3141E80002002AF3D100BF20684A -:10603000006800F0100010280AD100BF0020009076 -:1060400020680068009020684068009000BF00BF92 -:10605000A18D2046FDF7EDFE02E02046FEF745F952 -:106060000020F8BD01E00020FBE70220F9E7000076 -:106070002DE9F84F04462068006920F44050E1689B -:106080000843216808612169A068084361690843E1 -:10609000E169084300902068C06849F20C618843B8 -:1060A000009908432168C8602068406920F4407066 -:1060B000A16908432168486176492068884203D075 -:1060C00075492068884203D1FCF71CFB814602E039 -:1060D000FCF708FB8146E069B0F5004F6CD1022067 -:1060E0006168A0FB015003461920A9FB007001461E -:1060F0002A463846FAF7C6F86421B0FBF1F04FEAB9 -:10610000001A02206168A0FB01510B461920A9FB6F -:1061100000712A463846FAF7B5F8834602206168CE -:10612000A0FB015003461920A9FB00712A463846FE -:10613000FAF7A8F86421B0FBF1F000EBC00101EB25 -:106140000010ABEB8000322101EBC0006421B0FBFA -:10615000F1F000F0F8000AEB400A02206168A0FBB1 -:10616000015003461920A9FB007001462A46384613 -:10617000FAF788F8834602206168A0FB01500346C5 -:106180001920A9FB00712A463846FAF77BF86421EA -:10619000B0FBF1F000EBC00101EB0010ABEB8000B5 -:1061A000322101EBC0006421B0FBF1F000F00700E8 -:1061B0005044216888606AE004206168A0FB0150B7 -:1061C00003461920A9FB007001462A463846FAF713 -:1061D00059F8824604206168A0FB0150034619204B -:1061E000A9FB007001462A463846FAF74BF86421AD -:1061F000B0FBF1F000EBC00101EB0010AAEB800056 -:10620000322101EB00106421B0FBF1F000F0F00A44 -:1062100004206168A0FB017003461920A9FB00510E -:106220003A462846FAF72EF86421B0FBF1F00AEB63 -:10623000001A04206168A0FB01510B461920A9FB3C -:1062400000712A463846FAF71DF883460420616833 -:10625000A0FB015003461920A9FB007001462A4605 -:106260003846FAF70FF86421B0FBF1F000EBC001FB -:1062700001EB0010ABEB8000322101EB0010642138 -:10628000B0FBF1F000F00F00504421688860BDE8D9 -:10629000F88F0000001001400014014077B581B074 -:1062A000044615460298A062A5850020206422209D -:1062B00084F83E002A48A16BC8632A48A16B086491 -:1062C0002948A16BC8640020A16B086502AE326842 -:1062D0002368191D2B46A06BFAF7D0FE00BF0020E3 -:1062E000009020680068009020684068009000BF1F -:1062F00000BF00BF002084F83C0000BF206970B1DF -:1063000000BF00BF21680C3151E8001F41F48070CC -:1063100021680C3141E80002002AF3D100BF00BF20 -:1063200000BF2168143151E8001F41F001002168CD -:10633000143141E80002002AF3D100BF00BF00BFC2 -:106340002168143151E8001F41F0400021681431E8 -:1063500041E80002002AF3D100BF002004B070BD64 -:10636000F55D0008A55E0008A55D0008014691F8EE -:106370003D00212828D18868B0F5805F0BD10869DD -:1063800048B90A6A1088C0F308000B685860086AA8 -:10639000801C086205E00B6A581C086218780B68BC -:1063A0005860C88C401E80B2C88458B90868C0685C -:1063B00020F080000B68D8600868C06840F040009A -:1063C0000B68D860002070470220FCE72DE9F041FF -:1063D00004460D4617469846069E34E0701C88B366 -:1063E0002EB1FAF7BBFFA0EB0800B0422BD900BFDB -:1063F00000BF21680C3151E8001F21F4D0702168E2 -:106400000C3141E80002002AF3D100BF00BF00BFF9 -:106410002168143151E8001F21F001002168143176 -:1064200041E80002002AF3D100BF202084F83D009B -:1064300084F83E0000BF002084F83C0000BF032029 -:10644000BDE8F081FFE7206800682840A84201D13C -:10645000012000E00020B842C0D00020F0E700009A -:1064600008B50D480068006800F0100010280ED133 -:1064700000BF0020009008480068006800900648AF -:1064800000684068009000BF00BF06F023FC02488F -:10649000FDF7D2FC08BD0000A80600202DE9F04160 -:1064A00004460D46D4F8C87204F53070D4F8D412FE -:1064B00050F8210010B90320BDE8F08104F53070D8 -:1064C000D4F8D41250F8216005F00F0000EB8001E1 -:1064D00004F1140000EB8100406838B305F00F00B0 -:1064E00000EB800104F1140000EB8100416805F02D -:1064F0000F0000EBC00207F13C0000EB8200C06817 -:10650000B1FBF0F200FB121080B9002105F00F0082 -:1065100000EB800204F1140000EB820041600023D4 -:106520001A462946204601F02CF917E00020C6F84B -:10653000140204F53170D4F8D41250F82100006927 -:1065400060B1D6F8080204F53171D4F8D42251F8BC -:1065500022102A460B6906F5047198470020ABE724 -:1065600070B504460E4604F53070D4F8D41250F8D5 -:106570002150D4F8D41250F8210008B9032070BD7E -:106580003146204600F059FFC5F80C02D5F8040248 -:1065900004F53171D4F8D43251F82310CA6805F5E6 -:1065A000037190470020EAE770B504460D46304875 -:1065B0000178204600F013FE00212D48007800F0FD -:1065C0000F0000EB800204F1140000EB8200018256 -:1065D00028480178204600F002FE00212548007876 -:1065E00000F00F0000EB800204F5AA7000EB8200BF -:1065F000018221480178204600F0F1FD00211E486B -:10660000007800F00F0000EB800204F1140000EBB2 -:10661000820001821848007800F00F0000EB800231 -:1066200004F1140000EB8200418204F53070D4F8CC -:10663000D41250F82100C8B104F53171D4F8D42235 -:1066400051F822104868804704F53071D4F8D422FC -:1066500051F8220001F0BEFB002104F53070D4F89F -:10666000D42240F822100020C4F8BC02002070BDE3 -:106670001F020020200200202102002070B50446E5 -:1066800004F53070D4F8D41250F821500DB903201D -:1066900070BD04F53170D4F8D41250F8210098B1CF -:1066A00095F80002FF280FD095F8012295F8000216 -:1066B00004F53171D4F8D46251F826108B6829465C -:1066C0009847FF2085F800020020E1E701460A20F4 -:1066D0000880014870470000980100202DE9F04132 -:1066E000044682210D4800F0A0FC054601210B481C -:1066F00000F09BFC06468121084800F096FC074606 -:106700000DB11020A8710EB14020B0800FB1402013 -:10671000B880432020800148BDE8F081DC010020E2 -:106720002DE9F041044682210E4800F07EFC05462A -:1067300001210C4800F079FC06468121094800F04F -:1067400074FC07460DB11020A87116B14FF400700B -:10675000B08017B14FF40070B8804320208001480A -:10676000BDE8F081DC0100202DE9F04104468221E2 -:106770000D4800F05AFC054601210B4800F055FC7D -:1067800006468121084800F050FC07460DB1102054 -:10679000A8710EB14020B0800FB14020B8804320D6 -:1067A00020800148BDE8F081DC01002070B504467E -:1067B0000E464FF4077001F00FFB054645B9002166 -:1067C00004F53070D4F8D42240F82210022070BDB5 -:1067D0004FF407712846F9F79FFD04F53070D4F89F -:1067E000D41240F82150D4F8D41250F82100C4F843 -:1067F000BC02207C98BB4FF4007302225048017801 -:10680000204600F0BBFE01214D48007800F00F004B -:1068100000EB800204F1140000EB820001824B02C5 -:10682000022248480178204600F0A8FE0121454890 -:10683000007800F00F0000EB800204F5AA7000EB76 -:106840008200018210214048007800F00F0000EB28 -:10685000800204F1140000EB8200418232E0FFE785 -:106860004023022236480178204600F087FE0121AD -:106870003348007800F00F0000EB800204F11400B0 -:1068800000EB82000182402302222E48017820463C -:1068900000F074FE01212B48007800F00F0000EB9F -:1068A000800204F5AA7000EB8200018210212648C4 -:1068B000007800F00F0000EB800204F1140000EB00 -:1068C00082004182082303221F480178204600F0FD -:1068D00055FE01211C48007800F00F0000EB8002FB -:1068E00004F1140000EB820001820020C5F80402CC -:1068F00004F53171D4F8D42251F822100868804789 -:106900000020C5F81402C5F81802D5F8040208B929 -:1069100002205CE7207C48B94FF4007309480178F5 -:106920002046D5F8042200F041FE07E04023054848 -:1069300001782046D5F8042200F038FE002046E712 -:106940001F020020200200202102002070B5044612 -:1069500004F53070D4F8D41250F82150D4F8D41281 -:1069600050F8210008B9032070BD207C48B94FF4CD -:106970000073094801782046D5F8042200F016FE7D -:1069800007E04023044801782046D5F8042200F0AF -:106990000DFE0020E8E7000020020020024609B9B1 -:1069A0000320704702F53170D2F8D43240F823103A -:1069B0000020F6E710B5024602F53070D2F8D44256 -:1069C00050F824300BB9032010BDC3F80412002086 -:1069D000FAE730B503460C4603F53070D3F8D452CD -:1069E00050F8251009B9032030BDC1F80842C1F89C -:1069F00010220020F8E72DE9FC4105460C4605F57C -:106A00003070D5F8D41250F8216000200190009029 -:106A1000804616B90320BDE8FC81207800F06000B4 -:106A200000283DD020287CD1E08868B3207800F091 -:106A30008000B8B1E288607805F53171D5F8D4C22C -:106A400051F82C108B6831469847E088072801D907 -:106A5000072000E0E08807463A463146284600F025 -:106A600015F91CE0607886F80002E088402801D221 -:106A7000E08800E0402086F8010296F801223146C5 -:106A8000284600F0E2F80AE0607805F53171D5F8A3 -:106A9000D42251F8221000228B682146984747E003 -:106AA000607830B1012832D00A2813D00B282FD1BA -:106AB00021E095F89C02032805D102226946284668 -:106AC00000F0E4F805E02146284600F0B2F84FF067 -:106AD000030824E095F89C02032805D1012201A9AE -:106AE000284600F0D3F805E02146284600F0A1F83A -:106AF0004FF0030813E095F89C02032805D02146C7 -:106B0000284600F096F84FF0030808E009E006E098 -:106B10002146284600F08DF84FF0030800BF00BF63 -:106B200006E02146284600F084F84FF0030800BF35 -:106B300000BF40466FE7000070B5044604F53070B2 -:106B4000D4F8D41250F821500126D4F8D41250F8B9 -:106B5000210008B9032070BDD5F81402C8B901207E -:106B6000C5F814020C48007800F00F0000EB80021A -:106B700004F1140000EB8200D5F8101241600648C1 -:106B800001782046D5F81032D5F8082200F0F9FD3A -:106B900000263046DFE700001F02002070B50446E3 -:106BA0000D460026D4F8B802294642682046904790 -:106BB00000B10326304670BD70B504460D4694F80A -:106BC0009C02012804D0022803D003280CD101E044 -:106BD00000BF00BF6888012805D10020C4F8A402C6 -:106BE000204600F064F804E02946204600F021F831 -:106BF00000BF00BF70BD0246002070470246002063 -:106C0000704770B506460C4615462B4622460021B5 -:106C1000304600F0CBFC002070BD70B506460C4637 -:106C200015462B4622460021304600F0AAFD0020E2 -:106C300070BD70B504460D468021204600F075FDFC -:106C40000021204600F071FD70BD70B504460E466F -:106C500015460320C4F894024FF4AC700551001D92 -:106C600005512B4632460021204600F09FFC0020B3 -:106C700070BD10B504460520C4F8940200231A46DE -:106C80001946204600F092FC002010BD70B5044665 -:106C90000E4615460220C4F89402A561E5612B4614 -:106CA00032460021204600F06CFD002070BD10B57A -:106CB00004460420C4F8940200231A4619462046CC -:106CC00000F05FFD002010BD70B505460C462DB9E3 -:106CD0002246064906A000F012FA04E022460349C3 -:106CE00003A000F00CFA014870BD00006CF8002011 -:106CF00043444320436F6E666967000002461220DA -:106D000008800148704700004C01002070B505461E -:106D10000C462DB92246064906A000F0F0F904E021 -:106D20002246034903A000F0EAF9014870BD0000C3 -:106D30006CF8002043444320496E746572666163B9 -:106D400065000000024604200880014870470000EA -:106D50006001002070B505460C462246024903A09A -:106D600000F0CDF9004870BD6CF8002053544D6917 -:106D700063726F656C656374726F6E696373000034 -:106D800070B505460C462DB92246064906A000F00E -:106D9000B6F904E02246034903A000F0B0F9014827 -:106DA00070BD00006CF8002053544D3332205669FA -:106DB000727475616C20436F6D506F7274000000C7 -:106DC00070B505460C461A202080F9F739FF0148B6 -:106DD00070BD00006401002070B504460D46E888CF -:106DE000012804D029462046FFF723FF1EE094F82F -:106DF0009C02012804D0022803D0032810D109E006 -:106E000000BF0020A060012204F108012046FFF726 -:106E10003DFF0AE00122211D2046FFF737FF04E075 -:106E200029462046FFF705FF00BF00BF70BDF8B53B -:106E300004460E46002000900027002570880012AE -:106E4000082875D2DFE800F0C7040C20C7C7A5B535 -:106E5000207CD4F8B4120A68694690470746C1E01E -:106E6000207C40B9D4F8B802816A68468847074652 -:106E70000220787007E0D4F8B802C16A68468847F3 -:106E8000074602207870ADE0B078062878D2DFE8B7 -:106E900000F00316293C5063D4F8B402406838B1BE -:106EA000207CD4F8B4124A6869469047074605E04A -:106EB00031462046FFF7BDFE681CC5B267E0D4F836 -:106EC000B402806838B1207CD4F8B4128A6869466C -:106ED0009047074605E031462046FFF7AAFE681CAA -:106EE000C5B254E0D4F8B402C06838B1207CD4F8FC -:106EF000B412CA6869469047074605E03146204605 -:106F0000FFF797FE681CC5B241E0D4F8B4020069EF -:106F100038B1207CD4F8B4120A6969469047074614 -:106F200005E031462046FFF784FE681CC5B22EE01E -:106F300051E0D4F8B402406938B1207CD4F8B412DE -:106F40004A6969469047074605E031462046FFF703 -:106F500070FE681CC5B21AE0D4F8B402806940B172 -:106F6000207CD4F8B4128A6969469047074606E047 -:106F700006E031462046FFF75CFE681CC5B206E01D -:106F800031462046FFF755FE681CC5B200BF00BF62 -:106F900028E0207C30B9D4F8B802416B68468847B5 -:106FA000074605E031462046FFF743FE681CC5B2A0 -:106FB00018E0207C40B9D4F8B802016B68468847D5 -:106FC00007460720787005E031462046FFF731FE7E -:106FD000681CC5B206E031462046FFF72AFE681C51 -:106FE000C5B200BF00BF05B1F8BDF088C0B1BDF8A3 -:106FF000000080B1F088BDF80010884202DDBDF8C5 -:10700000000000E0F0880090BDF8002039462046DE -:10701000FFF73CFE07E031462046FFF70AFE02E09C -:107020002046FFF744FE00BFDEE72DE9F8410546A4 -:107030000F462C462E464FF0000870883178884263 -:1070400018DD307800900FE06946204600F020F807 -:1070500004466078052807D1A04698F80200B84297 -:1070600000D106E04FF000087088BDF8001088429B -:10707000EADC00BF4046BDE8F881014600200A4630 -:1070800002E0431CD8B2521C1378002BF9D1704790 -:1070900010B5024610460B88047823440B80037811 -:1070A000981810BD70B504460D4694F89C0201284E -:1070B00004D0022803D003281AD101E000BF00BF8A -:1070C000E888022804D029462046FFF7B2FD14E0E4 -:1070D0000120E060D4F8A40218B1E06840F002009A -:1070E000E060022204F10C012046FFF7CFFD04E02E -:1070F00029462046FFF79DFD00BF00BF70BD2DE96A -:10710000F04107460D46904600240FB9BDE8F081D6 -:107110003E463046FFF7B1FF022101EB4000A8F8E0 -:10712000000098F800002855601CC4B203202855C0 -:10713000601CC4B208E030782855761C601CC4B2CC -:1071400000202855601CC4B230780028F3D100BF5D -:10715000DCE70146002031B1012906D0022906D022 -:10716000032908D105E0002007E0032005E0012005 -:1071700003E0032001E0032000BF00BF70472DE9BA -:10718000F04104460D46164614B90320BDE8F081CF -:107190000020C4F8B802C4F8C402C4F8D0020DB18B -:1071A000C4F8B452012084F89C022670204600F0F6 -:1071B0004DF907463846E9E72DE9F04104460D460A -:1071C000002600272946D4F8C802FAF78EFA0646A8 -:1071D0003046FFF7BEFF07463846BDE8F0812DE98F -:1071E000F04104460D46002600272946D4F8C8027F -:1071F000FAF746FA06463046FFF7ABFF0746384631 -:10720000BDE8F0812DE9F04704460F469146002F76 -:1072100056D104F11405D4F89402022846D1D5E9D8 -:10722000020188420FD9D5E90201401AA8604946F7 -:107230002046AA68FFF7F1FC00231A4619462046AB -:1072400000F0B4F932E0D5E90210884217D1E968BC -:107250006868884213D36868D4F8981288420ED2BE -:10726000002211462046FFF7D8FC0020C4F89802FF -:1072700000231A461946204600F098F916E094F8C3 -:107280009C0203280BD1D4F8B802C06838B10020A2 -:10729000C4F8D402D4F8B802C168204688478021D7 -:1072A000204600F042FA2046FFF7E3FC94F8A002E3 -:1072B00050B3204600F0BCFA002084F8A00223E07E -:1072C00047F080012046FFF796FC0646FF2E1BD0B4 -:1072D000D6B994F89C02032816D104F52E7050F804 -:1072E0002600406980B1C4F8D46204F52E7050F8CD -:1072F000260039464269204690478046B8F1000F83 -:1073000002D04046BDE8F0870020FBE72DE9F047BA -:1073100005460F4690464FF00009002F51D105F564 -:10732000AA76D5F8940203286FD1D6E902018842E3 -:1073300010D9D6E90201401AB060D6E902018842AC -:1073400001D2B06800E0F068024641462846FFF7E7 -:1073500058FC5AE095F8AA0200F01F0020B101285D -:1073600004D0022812D109E0002411E040F2AE203E -:10737000415D2846FFF742FC044609E040F2AE209A -:10738000415D2846FFF737FC044601E0002400BFBA -:1073900000BF94B995F89C0203280ED105F52E7014 -:1073A00050F82400006940B1C5F8D44205F52E70AC -:1073B00050F824000169284688472846FFF777FCE3 -:1073C00023E007F07F012846FFF715FC0446FF2C59 -:1073D0001BD0D4B995F89C02032810D105F52E7066 -:1073E00050F82400806950B1C5F8D44205F52E70DC -:1073F00050F8240039468269284690478146B9F101 -:10740000000F02D04846BDE8F0870020FBE70146A8 -:107410000020704770B504460025012084F89C02C6 -:10742000D4F8B80238B12179D4F8B80242682046BD -:10743000904700B10325284670BD70B504460D463F -:107440002946D4F8C802FAF78EF970BD10B5044683 -:10745000207800282AD11648C0F80845C4F8C80288 -:107460004FF0A040124908600420486002211048F3 -:10747000C16000210161022181610021C1610162BD -:107480004162C1620163FAF7D4FD08B1F9F7A2FBCA -:1074900080210748FAF779F8402200210448FAF7DA -:1074A00079F8802201210248FAF774F8002010BD13 -:1074B0006C0A012010B50246D2F8C83201F08000F3 -:1074C000802809D101F07F0000EBC00403F13C00EB -:1074D00000EB8400807810BD01F07F0000EBC00459 -:1074E00003F51F7000EB84008078F4E770B5044664 -:1074F0000D4604F52E70D4F8D41250F8210008B9C6 -:10750000032070BD94F89C02032811D104F52E705D -:10751000D4F8D41250F82100006A48B104F52E7056 -:10752000D4F8D41250F821002946026A2046904728 -:107530000020E6E770B504460D4604F52E70D4F839 -:10754000D41250F8210008B9032070BD94F89C02B1 -:10755000032811D104F52E70D4F8D41250F821006C -:10756000406A48B104F52E70D4F8D41250F82100C6 -:107570002946426A204690470020E6E72DE9F04779 -:1075800004460F4615461E464FF00008C1462B46DE -:1075900032463946D4F8C802FAF7F0F88046404639 -:1075A000FFF7D7FD81464846BDE8F0872DE9F04753 -:1075B00004460D4616461F464FF00008C1463B469E -:1075C00032462946D4F8C802FAF71EF980464046EA -:1075D000FFF7BFFD81464846BDE8F08770B5044619 -:1075E0000025012084F89C020020C4F89402606009 -:1075F000C4F8A40284F8A002D4F8B80258B1D4F8B0 -:10760000B802406838B12179D4F8B80242682046FF -:10761000904700B103254023002211462046FFF782 -:10762000ADFF01214FF4B27001534021001F015101 -:107630004023002280212046FFF7A0FF0121A184E2 -:1076400040212162284670BD014691F89C02042821 -:1076500003D191F89D0281F89C020020704710B57B -:10766000044694F89C0203280BD1D4F8B80240B128 -:10767000D4F8B802C06920B1D4F8B802C169204674 -:107680008847002010BD02461174002070472DE984 -:10769000F04104460D46002600272946D4F8C802CA -:1076A000FAF7F4FD06463046FFF753FD0746384625 -:1076B000BDE8F08170B504460D46294604F2AA20C3 -:1076C00000F077F80120C4F894024FF42C70005BAE -:1076D000C4F8980294F8AA0200F01F0020B1012813 -:1076E00009D0022815D10DE004F2AA21204600F0AD -:1076F00083F9064616E004F2AA21204600F013FBA7 -:1077000006460FE004F2AA21204600F0CCF9064616 -:1077100008E094F8AA0200F08001204600F005F885 -:10772000064600BF00BF304670BD2DE9F04104465B -:107730000D46002600272946D4F8C802FAF790F82B -:1077400006463046FFF705FD07463846BDE8F0819E -:1077500070B5044600250026D4F8C802FAF7BAFD31 -:1077600005462846FFF7F5FC0646304670BD014643 -:1077700091F89C0281F89D02042081F89C0200206F -:1077800070472DE9F04704460D4616461F464FF058 -:107790000008C1463B4632462946D4F8C802FAF7EB -:1077A000A4F880464046FFF7D4FC81464846BDE831 -:1077B000F08770B505460E46344620782870641C64 -:1077C00020786870641C2046FEF7DEF96880641C2F -:1077D000641C2046FEF7D8F9A880641C641C20466F -:1077E000FEF7D2F9E88070BD38B504460D4600209A -:1077F00000900DB9032038BDC4F8B85204F52E70BE -:10780000D4F8D41250F82100C06A50B104F52E709B -:10781000D4F8D42250F82200C16A68468847C4F8D8 -:10782000D002D4F8D802401CC4F8D8020020E2E705 -:1078300001460020704770B504460D46A88810BB6D -:10784000E88800BB688880281DD2A87800F07F06F1 -:1078500094F89C02032804D129462046FFF7E9F951 -:1078600015E084F89E6231462046FFF710FF20465F -:10787000FFF71DFA1EB1022084F89C0207E00120E8 -:1078800084F89C0203E029462046FFF7D2F970BD38 -:1078900070B504460D460026D4F8B80230B1D4F8CD -:1078A000B80229460268204690470646304670BD19 -:1078B00070B504460E460025B0783D49087008466C -:1078C0000078012805D931462046FFF7B2F9032098 -:1078D00070BD94F89C02022802D0032859D11FE001 -:1078E00033480078C0B13248007860603048017891 -:1078F0002046FFF7CDFF05463DB131462046FFF754 -:1079000098F9022084F89C0209E02046FFF7CFF99D -:10791000032084F89C0202E02046FFF7C8F943E008 -:107920002348007870B9022084F89C02204800782F -:1079300060601F4801782046FFF730F92046FFF7C6 -:10794000B6F925E01A490978606888421DD0217986 -:107950002046FFF723F91648007860601448017844 -:107960002046FFF795FF05465DB131462046FFF7FB -:1079700060F921792046FFF711F9022084F89C0272 -:1079800006E02046FFF793F902E02046FFF78FF963 -:107990000AE031462046FFF74CF9054801782046B9 -:1079A000FFF7FCF8032500BF00BF284690E7000062 -:1079B0009401002070B505460C466088012805D169 -:1079C000C5F8A4022846FFF772F90EE06088022885 -:1079D00007D1A088001285F8A0022846FFF767F9B2 -:1079E00003E021462846FFF724F970BD10B5044690 -:1079F0002046FFF7ADFE10BD70B504460D460026CB -:107A0000287800F0600088B1202802D0402842D1B8 -:107A100000E000BF04F52E70D4F8D41250F8210015 -:107A20002946826820469047064639E068780A2849 -:107A30002AD2DFE800F01A24291F290A0529150F88 -:107A400029462046FFF7F3F923E029462046FFF7B1 -:107A5000F2FE1EE029462046FFF72AFF064618E000 -:107A600029462046FFF7B8F913E029462046FFF7DC -:107A700019FB0EE029462046FFF79CFF09E0294646 -:107A80002046FFF799F804E029462046FFF7D1F891 -:107A900000BF00BF04E029462046FFF7CAF800BF38 -:107AA00000BF304670BD2DE9F04705460F464FF048 -:107AB00000093C79387800F06000F8B1202802D045 -:107AC00040287DD100E000BF21462846FFF793F80B -:107AD0000646FF2E11D086B9C5F8D46205F52E7082 -:107AE00050F82600806840B105F52E7050F8260049 -:107AF0003946826828469047814610E17878002808 -:107B00007AD001282FD003286ED195F89C02022844 -:107B100002D0032820D110E054B1802C08D0214697 -:107B20002846FFF702FE80212846FFF7FEFD03E00E -:107B300039462846FFF77DF813E0788840B93CB114 -:107B4000802C05D0F88818B921462846FFF7EDFDAE -:107B50002846FFF7ACF804E039462846FFF769F8F5 -:107B600000BF00BFD4E095F89C02022802D0032891 -:107B70003BD110E054B1802C08D021462846FFF7B5 -:107B8000D4FD80212846FFF7D0FD03E03946284682 -:107B9000FFF74FF82EE0788820BB04F07F0018B183 -:107BA00021462846FFF708FB2846FFF780F82146C4 -:107BB0002846FFF720F80646FF2E13D096B900E0BE -:107BC000A8E0C5F8D46205F52E7050F8260080684C -:107BD00040B105F52E7050F82600394682682846D7 -:107BE0009047814606E007E08DE039462846FFF7DA -:107BF00020F800BF00BF8BE095F89C02022802D05D -:107C0000032879D126E034B1802C04D039462846A7 -:107C1000FFF70FF875E004F08000802808D104F029 -:107C20007F0000EB800105F1140000EB810007E00C -:107C300004F07F0000EB800105F5AA7000EB8100E5 -:107C400080460020C8F80000022241462846FFF77F -:107C50001DF856E004F0800080280ED104F00F00DB -:107C600000EB800105F1140000EB8100008A98B957 -:107C700039462846FEF7DDFF43E004F00F0000EB35 -:107C8000800105F5AA7000EB8100008A20B9394611 -:107C90002846FEF7CEFF34E004F08000802808D1AB -:107CA00004F07F0000EB800105F1140000EB81007F -:107CB00007E004F07F0000EB800105F5AA7000EBFF -:107CC000810080460CB1802C03D10020C8F8000050 -:107CD0000CE021462846FFF7EDFB20B10120C8F853 -:107CE000000003E008E00020C8F80000022241463E -:107CF0002846FEF7CBFF04E039462846FEF799FFF9 -:107D000000BF00BF04E039462846FEF792FF00BFDF -:107D100000BF04E039462846FEF78BFF00BF00BFD6 -:107D20004846BDE8F0872DE9F04105460E4600279C -:107D3000307800F0600030B1202802D0402840D1D7 -:107D400000E000BF00BF95F89C02012804D0022883 -:107D500003D003282ED101E000BF00BF30790128F5 -:107D600023D831792846FEF749FF0446FF2C14D06A -:107D70009CB905F52E7050F82400806858B1C5F8FC -:107D8000D44205F52E7050F824003146826828460A -:107D90009047074602E0032700E00327F08840B938 -:107DA0003FB92846FEF783FF03E031462846FEF739 -:107DB00040FF04E031462846FEF73BFF00BF00BF0E -:107DC00004E031462846FEF734FF00BF00BF3846C6 -:107DD000BDE8F0817047000001460148704700008F -:107DE000780F012070B504460B4622461978587862 -:107DF00001282CD140F61C0080581D7805F00F0694 -:107E00000125B540ADB2284340F61C05A85002F547 -:107E1000106000EB4110006800F40040F0BB98894E -:107E2000C0F30A001D7940EA854040EA815040F0E5 -:107E3000805040F4004002F5106505EB41152D68B7 -:107E4000284302F5106505EB411528602DE040F64A -:107E50001C0080581D7805F00F060125B540144E12 -:107E600006EA0545284340F61C05A85002F5306097 -:107E700000EB4110006800F4004078B99889C0F325 -:107E80000A001D7940EA854040F0805040F40040EF -:107E900002F5306505EB41152D6800E005E028434B -:107EA00002F5306505EB41152860002070BD00002B -:107EB0000000FFFF01460A464FF410608058C30AD5 -:107EC000DB024FF41060835040F60400805840F409 -:107ED000807340F604008350002070470FB470B5E3 -:107EE00004460A98012817D1A06B20F48030A063C3 -:107EF000E0681A490840E060E06820F44010E06063 -:107F00001198012803D1E06840F48010E060204619 -:107F100000F026F8054612E0E06840F04000E0601E -:107F2000204600F01DF805460E9820B9A06B40F4DD -:107F30008030A06303E0A06B20F48030A063089839 -:107F4000012807D1A06840F00600A060A06840F0BA -:107F50002000A060284670BC5DF814FBBFFFBDFF89 -:107F600008B501460020009000BF0098401C00901A -:107F7000104A0098904201D9032008BD086900F01A -:107F800000400028F1D000200090086940F0010076 -:107F9000086100BF0098401C0090064A009890427B -:107FA00001D90320E9E7086900F001000028F1D1B8 -:107FB00000BFE2E7400D030070B504460B462246C1 -:107FC00019785878012848D102F5106000EB41106B -:107FD000006800F00040B0F1004F17D102F51060CA -:107FE00000EB4110006840F0006502F5106000EB06 -:107FF0004110056002F5106000EB4110006840F090 -:10800000804502F5106000EB4110056040F63C0031 -:1080100080581D7805F00F060125B540ADB2A84384 -:1080200040F63C05A85040F61C0080581D7805F02D -:108030000F060125B540ADB2A84340F61C05A85077 -:1080400002F5106000EB411000682B4D284002F54E -:10805000106505EB411528604BE002F5306000EB40 -:108060004110006800F00040B0F1004F17D102F558 -:10807000306000EB4110006840F0006502F53060B0 -:1080800000EB4110056002F5306000EB4110006824 -:1080900040F0804502F5306000EB4110056040F68D -:1080A0003C0080581D7805F00F060125B540134EA1 -:1080B00006EA0545A84340F63C05A85040F61C00DA -:1080C0008558187800F00F060120B0400B4E06EAE4 -:1080D0000040854340F61C00855002F5306000EBFF -:1080E00041100068064D284002F5306505EB41154A -:1080F0002860002070BD0000007833EC0000FFFF16 -:108100000078F3EF01460A46D2F8000E20F0030093 -:10811000C2F8000E40F60400805820F0020340F63A -:10812000040083500020704701460A46D2F8000E32 -:1081300020F00300C2F8000E40F60400805840F022 -:10814000020340F604008350002070470FB4F0B5DE -:10815000054600272E46002405E0002105F5827023 -:1081600040F82410641C0F2CF7D31098A0B940F6E7 -:108170000400805940F0020140F604008151A86BD0 -:1081800040F40010A863A86B20F40020A863A86B3B -:1081900020F48020A86307E0A86B20F40010A863F7 -:1081A000A86B40F40020A8630020C6F8000ED6F8A3 -:1081B0000008C6F800080B9801280BD1089820B9D0 -:1081C0000021284600F0BCFD08E00121284600F00F -:1081D000B7FD03E00321284600F0B2FD1021284638 -:1081E00000F0B2FC00B10127284600F083FC00B18A -:1081F000012700214FF401608151001D815140F69B -:108200001C00815100242EE006F5106000EB4410A4 -:10821000006800F00040B0F1004F10D13CB94FF0C1 -:10822000006106F5106000EB441001600DE04FF0B6 -:10823000904106F5106000EB4410016005E000215C -:1082400006F5106000EB44100160002106F5106097 -:1082500000EB441001614FF67F3106F5106000EB32 -:1082600044108160641C0698A042CDD800242EE002 -:1082700006F5306000EB4410006800F00040B0F1FB -:10828000004F10D13CB94FF0006106F5306000EBB3 -:10829000441001600DE04FF0904106F5306000EBB6 -:1082A0004410016005E0002106F5306000EB441049 -:1082B0000160002106F5306000EB441001614FF6CB -:1082C0007F3106F5306000EB44108160641C069835 -:1082D000A042CDD84FF40160805920F480714FF452 -:1082E000016081510020A8616FF0804068610998A9 -:1082F00018B9A86940F01000A861A86909490843A5 -:10830000A8610C9818B1A86940F00800A8611098FD -:10831000012803D1A86904490843A8613846F0BC84 -:108320005DF814FB00383C8004000040014688687A -:1083300020F001008860002070470000F0B505467D -:108340000B4614462A4619785878012875D1986941 -:1083500020BB02F5106000EB411000696D4E30400B -:1083600002F5106606EB4116306102F5106000EB75 -:108370004110006940F4002602F5106000EB411046 -:10838000066102F5106000EB41100069C60CF604AE -:1083900002F5106000EB4110066137E002F5106055 -:1083A00000EB41100069C60CF60402F5106000EB0A -:1083B0004110066102F5106000EB41100069554E56 -:1083C000304002F5106606EB41163061DE689869B0 -:1083D000B04201D9D868986102F5106000EB4110F5 -:1083E000006940F4002602F5106000EB41100661C0 -:1083F00002F5106000EB411000699E69C6F3120699 -:10840000304302F5106606EB41163061012C15D1A0 -:10841000586928B102F5106000EB41105E694661B1 -:1084200002F5106000EB4110006840F0044602F5D0 -:10843000106000EB411006606AE01BE002F510607E -:1084400000EB4110006840F0044602F5106000EBBC -:1084500041100660986900285AD040F634008058D0 -:108460001E7806F00F070126BE40304340F6340662 -:10847000B0504DE002F5306000EB41100069C60CD1 -:10848000F60402F5306000EB4110066102F5306041 -:1084900000EB411000691F4E304002F5306606EBDC -:1084A00041163061986908B1D8689861D868D86178 -:1084B00002F5306000EB4110006940F4002602F53F -:1084C000306000EB4110066102F5306000EB4110B6 -:1084D0000069DE69C6F31206304302F5306606EB2A -:1084E00041163061012C07D1186928B102F53060BE -:1084F00000EB41101E69466102F5306000EB41104F -:10850000006840F0044602F5306000EB4110066060 -:108510000020F0BDFFFF07E070B503460C4619468A -:108520001D6C1848854209D94FF43060405800F05E -:108530000040B0F1004F01D1002070BD0026C1F80D -:10854000106BD1F8100B40F40026C1F8106BD1F875 -:10855000100B40F01806C1F8106BD1F8100B40F06A -:10856000C046C1F8106B012C09D1C1F8142B4FF48F -:108570003060405840F080264FF430604650002074 -:10858000DBE700000A30544F30B504460B46224664 -:108590001978587801281ED102F5106000EB4110BF -:1085A000006820F4001502F5106000EB4110056032 -:1085B0001879032802D0187902282AD102F5106010 -:1085C00000EB4110006840F0805502F5106000EBB0 -:1085D000411005601DE002F5306000EB41100068BD -:1085E00020F4001502F5306000EB411005601879A9 -:1085F000032802D0187902280BD102F5306000EB75 -:108600004110006840F0805502F5306000EB4110E9 -:108610000560002030BD30B504460B46224619786F -:108620005878012821D102F5106000EB4110006854 -:1086300000F0004060B959B102F5106000EB411044 -:10864000006820F0804502F5106000EB41100560E5 -:1086500002F5106000EB4110006840F4001502F5CF -:10866000106000EB4110056020E002F5306000EB87 -:108670004110006800F0004060B959B102F5306067 -:1086800000EB4110006820F0804502F5306000EBFF -:108690004110056002F5306000EB4110006840F4C5 -:1086A000001502F5306000EB41100560002030BD80 -:1086B0002DE9F84381460E4617464D4634787078CA -:1086C00001287DD1B06920BB05F5106000EB441096 -:1086D0000069C849084005F5106101EB44110861C3 -:1086E00005F5106000EB4410006940F4002105F529 -:1086F000106000EB4410016105F5106000EB4410C0 -:108700000069C10CC90405F5106000EB441001615B -:1087100055E005F5106000EB44100069C10CC90478 -:1087200005F5106000EB4410016105F5106000EBE9 -:1087300044100069AF49084005F5106101EB441190 -:108740000861F168B0690844401EB0FBF1F0A94926 -:10875000C94301EAC04005F5106101EB4411096904 -:10876000084305F5106101EB4411086105F510603F -:1087700000EB44100069B169C1F31201084305F52B -:10878000106101EB441108613079012817D105F51A -:10879000106000EB4410006920F0C04105F5106046 -:1087A00000EB4410016105F5106000EB4410006916 -:1087B00040F0005105F5106000EB4410016100E04D -:1087C0007FE0012F36D1706928B105F5106000EB0C -:1087D000441071694161307901281ED140F60800CA -:1087E000405900F4807060B905F5106000EB44104A -:1087F000006840F0005105F5106000EB4410016086 -:108800000BE005F5106000EB4410006840F080516B -:1088100005F5106000EB4410016005F5106000EBF9 -:108820004410006840F0044105F5106000EB44106E -:108830000160DCE005F5106000EB4410006840F0DA -:10884000044105F5106000EB441001603079012807 -:108850000FD0B0690028ECD040F634004059317890 -:1088600001F00F0201219140084340F634014851C4 -:10887000BDE040F60800405900F4807060B905F58D -:10888000106000EB4410006840F0005105F51060E6 -:1088900000EB441001600BE005F5106000EB4410A4 -:1088A000006840F0805105F5106000EB4410016055 -:1088B0000097308B83B232784846316900F0BEFAB7 -:1088C00095E005F5306000EB44100069C10CC90467 -:1088D00005F5306000EB4410016105F5306000EBF8 -:1088E000441000694349084005F5306101EB44112B -:1088F0000861B069D0B905F5306000EB441000693B -:10890000F168C1F31201084305F5306101EB441130 -:10891000086105F5306000EB4410006940F4002167 -:1089200005F5306000EB4410016128E0F168B069A2 -:108930000844401EB0FBF1F01FFA80F8F06800FB1D -:1089400008F0F06105F5306000EB4410006929493A -:10895000C94301EAC841084305F5306101EB441100 -:10896000086105F5306000EB44100069F169C1F35E -:108970001201084305F5306101EB44110861012F34 -:1089800007D1306928B105F5306000EB441031693A -:108990004161307901281ED140F60800405900F4A9 -:1089A000807060B905F5306000EB4410006840F05D -:1089B000005105F5306000EB441001600BE005F557 -:1089C000306000EB4410006840F0805105F53060E5 -:1089D00000EB4410016005F5306000EB44100068C6 -:1089E00040F0044105F5306000EB441001600020C8 -:1089F000BDE8F883FFFF07E078B503460024009444 -:108A000000201A464C78012C35D10C7802F51065FF -:108A100005EB4414246804F00044B4F1004F60D125 -:108A20000C7805EB4414246844F000660C7805EBE0 -:108A3000441426600C7805EB4414246844F0804606 -:108A40000C7805EB4414266000BF009C641C009465 -:108A500042F21075009CAC4201D901200AE00C786A -:108A600002F5106505EB4414246804F00044B4F1E9 -:108A7000004FEAD035E00C7802F5306505EB441480 -:108A8000246804F00044B4F1004F2AD10C7805EBBF -:108A90004414246844F000660C7805EB4414266006 -:108AA0000C7805EB4414246844F080460C7805EB00 -:108AB0004414266000BF009C641C009442F21075B0 -:108AC000009CAC4201D901200AE00C7802F5306527 -:108AD00005EB4414246804F00044B4F1004FEAD0DC -:108AE00000BF78BD0146886840F001008860002022 -:108AF0007047000008B501460020009000BF0098B4 -:108B0000401C00900F4A0098904201D9032008BDF4 -:108B1000086900F000400028F1D0002000901020EB -:108B2000086100BF0098401C0090064A00989042DF -:108B300001D90320EBE7086900F010001028F1D0FC -:108B40000020E4E7400D030008B502460020009035 -:108B500000BF0098401C0090104B0098984201D92B -:108B6000032008BD106900F000400028F1D000206B -:108B70000090202040EA8110106100BF0098401C46 -:108B80000090064B0098984201D90320E9E710694C -:108B900000F020002028F1D00020E2E7400D030083 -:108BA00010B501460B4640F60804E45804F00602EE -:108BB0000AB9002006E0022A01D0062A01D10220CB -:108BC00000E00F2010BD0146486900F00100704729 -:108BD00001460B4640F61800C258001DC05802401E -:108BE00090B2704701460B4640F61800C258001D6F -:108BF000C0580240100C704770B5024613464FF43F -:108C00000166F45840F63406F55801F00F0625FACF -:108C100006F606F0010644EAC61403F5106606EBF4 -:108C20004116B66806EA040070BD10B50246134648 -:108C300003F5306404EB4114A06840F61404E458D2 -:108C4000204010BD014648698A69104070472DE9EF -:108C5000F04104460D46274628464FEA920C02F0A2 -:108C6000030300210AE04FF4805858F80780C0F849 -:108C70000080401C401C401C401C491C6145F2D334 -:108C80009BB100214FF4805858F8076000BF4FEAAD -:108C9000C10826FA08F880F80080491C401CA3F19E -:108CA00001081FFA88F3002BF1D1BDE8F08170B5FF -:108CB00004460E460025E06820F0C040E060012E2A -:108CC00010D1E06840F00050E06000BF0120F8F7EC -:108CD0001FFA6D1C2046FFF776FF012815D0322DB4 -:108CE000F4D312E07EB9E06840F08040E06000BF5D -:108CF0000120F8F70DFA6D1C2046FFF764FF20B144 -:108D0000322DF5D301E0012070BD322D01D10120BB -:108D1000FAE70020F8E710B502460B461146D1F8F5 -:108D2000000820F4FE60C1F80008D1F800084FF4F4 -:108D3000FE6404EA03142043C1F80008002010BDBB -:108D400002461346D3F800080843C3F80008002081 -:108D50007047000030B503461446022C49D12D4817 -:108D6000814204D32C48814201D20F2245E02A4897 -:108D7000814204D32948814201D20E223DE0274896 -:108D8000814204D32648814201D20D2235E0244895 -:108D9000814204D32348814201D20C222DE0214894 -:108DA000814204D32048814201D20B2225E01E4893 -:108DB000814204D31D48814201D20A221DE01B4892 -:108DC000814204D31A48814201D2092215E0184891 -:108DD000814204D31748814201D208220DE0154890 -:108DE000814204D31448814201D2072205E00622C1 -:108DF00003E00CB9092200E00922D86820F4705081 -:108E0000D860D8684FF4705505EA82252843D860A9 -:108E1000002030BDC0ACD800C0E1E4000024F40064 -:108E200080730601A0491A01002D310140A44C01B4 -:108E300000366E0120ABA6010048E8012DE9F043A1 -:108E400004460D461E46DDF81CC0A0462946BCF16E -:108E5000000F12D1F01C870800230CE0D1F800901D -:108E600008F5805000EB0230C0F80090491C491C06 -:108E7000491C491C5B1CBB42F0D30020BDE8F083B9 -:108E800000BFFEE70FB4084B10B504A902AA03986F -:108E900000F046FC044602A9002001F061F92046DA -:108EA00010BC5DF814FB000061A100087CB50C004B -:108EB0001D461646014601D0601E00E00020CDE9A7 -:108EC0000010064B6A462946304600F029FC002C6B -:108ED00002D0009A002111707CBD000069A000083A -:108EE00002480068C0F30220704700000CED00E06B -:108EF00010B5002804DB0A07130E054A135406E0D8 -:108F00000A07140E034A00F00F031B1FD45410BDB0 -:108F100000E400E018ED00E002E008C8121F08C1FC -:108F2000002AFAD170477047002001E001C1121FEA -:108F3000002AFBD170472DE9FC410446A089401E60 -:108F400080B200906089401E83B200221146204604 -:108F5000266FB0472068006A006800684FF6BF714E -:108F600008402168096A096808602068006A00688A -:108F7000006840F400602168096A09680860206898 -:108F8000006A0068006840F040002168096A0968CA -:108F9000086020680169D1E90401CDE90001206879 -:108FA0000669F7683B4696E80700B847002508E0E1 -:108FB000608A2168096A0968C860206801F0E8F8D9 -:108FC0006D1C6089A1894843A842F1D8206801F04E -:108FD000D6F820680169D1E90401CDE900012068D3 -:108FE0000669D6E902733A46D6E90001B847206817 -:108FF000006A006800684FF6BF7108402168096A7E -:10900000096808602068006A006800684FF2FF7114 -:1090100008402168096A096808602068006A0068D9 -:10902000006840F040002168096A09680860BDE8EE -:10903000FC8100002DE9FE4F0446884691461D46FE -:109040000026B2460027B346A5F12000C5B220682D -:109050000169D1E90401CDE900012068D0F810E0F0 -:10906000DEF80CC063469EE80700E04700BF33E02F -:10907000A0690068A169098905FB0161405C029053 -:109080004FF0000A22E0029800F0010028B1A08A07 -:109090002249096821F8170004E0608A1F4909681D -:1090A00021F81700029840100290781C87B20BF14B -:1090B00001001FFA80FBA0698088584502D14FF05B -:1090C000000B06E00AF101001FFA80FABAF1080F5E -:1090D000D9DB00BF701C86B2A0690089B042C7DC32 -:1090E000A069C0884844401E80B20090A069808872 -:1090F0004044401E83B24A4641462046D4F870C0E0 -:10910000E047A0698088A169C988484382B20348C2 -:109110000168204601F045F8BDE8FE8F2C010020D3 -:109120002DE9FE4F0446884691461E46002500273D -:109130000020029083461BE0E06902680089691CF8 -:109140004843105C317888420BD1E069028901689C -:10915000681C00FB021040787178884201D1AA4651 -:1091600007E0A81C85B2E0694089A84200DC00E065 -:10917000E2E700BF0025002733E0E0690068E1690D -:1091800009890AFB0100C05D01900020029022E0E5 -:10919000019800F0010028B1A08A2349096821F84C -:1091A000150004E0608A2049096821F81500681C50 -:1091B00085B20198401001900BF101001FFA80FB6D -:1091C000E0698088584502D14FF0000B06E0029814 -:1091D000401C80B2029002980828D9DB00BF781C9E -:1091E00087B2E0690089B842C7DCE069C0884844BA -:1091F000401E80B20090E06980884044401E83B2E7 -:109200004A4641462046D4F870C0E047E06980886D -:10921000E169C988484382B203480168204600F0EA -:10922000C0FFBDE8FE8F00002C0100202DE9F041B9 -:1092300005460E4617461C4619E020787F280BDCB1 -:1092400023783A4631462846FFF7F4FEA86980881D -:10925000304486B2641C0AE023463A46314628462A -:10926000FFF75EFFE8698088304486B2A41C20784E -:109270000028E2D1BDE8F0812DE9FF5F82B0002136 -:10928000DDE90430020DDDF840B0034318D044F6A8 -:109290001050A2F2FF3242431514119801281FD03A -:1092A000A5EB0B00401C5FEA000A4FF000064E4F92 -:1092B000DFF83891B046504615D5CAF1000413E0E6 -:1092C000119801244AA3012801D16FEA0B010298E9 -:1092D000119AC0E90031C0E9024206B0BDE8F09F32 -:1092E000CBF10000DFE704460021404A491842EB79 -:1092F0000450CDE9001012E0E00707D032463B46AB -:1093000040464946F7F7DEF88046894632463B46F6 -:1093100010461946F7F7D6F806460F466410002C9B -:10932000EAD1DDE90401DDE90023BAF1000F06DA34 -:10933000F7F7C8F842464B46F7F7C4F805E0F7F7E9 -:10934000D7F942464B46F7F7D3F904460E460022BA -:10935000284BF7F755FA03D84FF0FF30014607E0E6 -:109360000022254B20463146F7F705F8F7F72FFA8C -:10937000102409E0002C0ADB0A220023F6F782FF02 -:10938000039B30321A55641E50EA0102F2D1641C6C -:10939000039AC4F111031444119A012A03D0012243 -:1093A00008430DD10AE0084304D000204FF0110B10 -:1093B000119072E7A3EB0B056D1E0DE05B4504DD1C -:1093C0004FF0000205F1010504E003DA4FF000025E -:1093D000A5F10105002AECD002981199C0E90231EB -:1093E000C0E9004579E70000000014400000F03FAC -:1093F000300000000000F0430000E03F30B50022E4 -:109400000023002401F478052A0A01F47C456B0945 -:10941000C1F3C40442EA03052543458230BD000080 -:10942000014601F1100000E0001D02681AB9024A6D -:1094300012689042F8D370478400002070B504464B -:109440000D460CB1012100E00021084640F2051153 -:10945000F7F710FB0DB1012100E0002108464FF4A1 -:109460008371F7F707FB002084F831002562206A3A -:109470000068006840F04000216A0968086070BD1B -:109480007CB504460A20F7F743FE4FF48055294681 -:10949000012001F097FA9749086008460068A06229 -:1094A00020680169D1E90401CDE90001206805695E -:1094B000EE68334695E80700B0473621206800F093 -:1094C000E5FE0021206800F01BFF3A21206800F033 -:1094D000DDFE0521206800F013FFB221206800F0B6 -:1094E000D5FE0C21206800F00BFF0C21206800F055 -:1094F00007FF0021206800F003FF3321206800F0FF -:10950000FFFE3321206800F0FBFEB721206800F049 -:10951000BDFE3521206800F0F3FEBB21206800F07D -:10952000B5FE1921206800F0EBFEC021206800F094 -:10953000ADFE2C21206800F0E3FEC221206800F07F -:10954000A5FE0121206800F0DBFEC321206800F0A9 -:109550009DFE1221206800F0D3FEC421206800F097 -:1095600095FE2021206800F0CBFEC621206800F087 -:109570008DFE0F21206800F0C3FED021206800F08E -:1095800085FEA421206800F0BBFEA121206800F028 -:10959000B7FEE021206800F079FED021206800F0BD -:1095A000AFFE0421206800F0ABFE0D21206800F022 -:1095B000A7FE1121206800F0A3FE1321206800F00F -:1095C0009FFE2B21206800F09BFE3F21206800F0C9 -:1095D00097FE5421206800F093FE4C21206800F093 -:1095E0008FFE1821206800F08BFE0D21206800F00E -:1095F00087FE0B21206800F083FE1F21206800F009 -:109600007FFE2321206800F07BFEE121206800F02E -:109610003DFED021206800F073FE0421206800F098 -:109620006FFE0C21206800F06BFE1121206800F015 -:1096300067FE1321206800F063FE2C21206800F0F3 -:109640005FFE3F21206800F05BFE4421206800F0AF -:1096500057FE5121206800F053FE2F21206800F0B2 -:109660004FFE1F21206800F04BFE1F21206800F0F4 -:1096700047FE2021206800F043FE2321206800F0EF -:109680003FFE2121206800F001FE1121206800F03A -:10969000FDFD7820F7F73CFD2921206800F0F6FD5C -:1096A000206800F06CFD20680169D1E90401CDE972 -:1096B000000120680569D5E902633246D5E9000159 -:1096C000B04702212046E26D904700212046E26E1D -:1096D00090476FF07F412046226E90472046616F91 -:1096E0008847842002590449204690470020A075ED -:1096F0007CBD00002C010020FC00002010B50648B5 -:10970000046803E02046FFF78BFE04460348006828 -:109710008442F7D310BD00008000002084000020A8 -:109720002DE9FF4F95B09A46884606460025EEE1A2 -:10973000252877D100242746F94A0121039400E027 -:10974000044316F8013F203B01FA03F01042F7D121 -:1097500030782A2811D06FF02F033078A0F1300232 -:10976000092A16D8039A44F0020402EB820203EBA2 -:1097700042021044761C0390EFE758F8042B039242 -:10978000002A03DA504244F40054039044F00204E7 -:10979000761C30782E2816D116F8010F44F00404F8 -:1097A0002A280DD06FF02F023078A0F13003092B5A -:1097B00009D807EB870302EB4303C718761CF3E7CE -:1097C00058F8047B761C30786C280FD006DC4C28C7 -:1097D00017D068280DD06A2814D104E0742810D05E -:1097E0007A280FD10DE044F400140AE044F4801408 -:1097F00001E044F440147278824202D104F58014EE -:10980000761C761C307866280BD013DC582877D06D -:1098100009DC002875D04528F6D04628F4D0472822 -:109820001AD193E118E0632835D0642879D06528EF -:1098300012D18BE1702873D008DC6728F1D0692839 -:109840006FD06E280DD06F2806D1ACE073282CD0D5 -:10985000752874D0782853D05246179990476D1CBC -:1098600054E1C4F30250022809D003280DD0D8F8DF -:10987000001004280DD00D6008F1040846E1D8F866 -:109880000010EA17C1E90052F6E7D8F800100D8081 -:10989000F2E70D70F0E718F8041B8DF800100020B7 -:1098A0008DF80100EB46012003E058F804BB4FF0AF -:1098B000FF3061074FF0000102D40DE009F1010112 -:1098C0008946B9420FDA8145F8DB1BF809100029F7 -:1098D000F4D108E009F1010189468142FADB1BF865 -:1098E00009100029F6D103985346A0EB0907214639 -:1098F0003846179A00F080FA284400EB090507E083 -:1099000044E008E10DE01BF8010B5246179990471F -:10991000B9F10109F7D2534621463846179AF2E0C9 -:1099200039E00A21C4F302524FF0000B0091022AE1 -:1099300006D058F8040BC117032A09D00AE023E027 -:1099400008F1070020F00702F2E80201904605E066 -:1099500000B2C117042A01D140B2C117002906DAAA -:109960000A460021404261EB02012D2202E022055D -:1099700004D52B228DF80420012203E0E20701D058 -:109980002022F7E7914657E00A2100E010214FF02E -:10999000000B00910BE010214FF0000B44F0040489 -:1099A0000827009103E008204FF0000B0090C4F35B -:1099B0000252022A05D058F8040B0021032A08D0CD -:1099C00008E008F1070020F00702F2E802019046E3 -:1099D00003E080B2042A00D1C0B24FF00009220790 -:1099E0002AD53278702A07D0DDF800C08CF0100C30 -:1099F0005CEA0B0C05D00EE040228DF80420012219 -:109A000008E050EA010306D030238DF804308DF8C9 -:109A1000052002229146009B83F0080353EA0B03C2 -:109A20000AD150EA010201D1620705D530228DF832 -:109A300004204FF001097F1E3278582A04D039A241 -:109A40000C920CAA02920BE03BA2F9E75B46009A4B -:109A5000F6F718FC0C9B9B5C029A521E0292137044 -:109A600050EA0102F2D1029804A9081A00F1200B71 -:109A7000600702D524F4803400E001275F4502DD51 -:109A8000A7EB0B0000E0002000EB0B010090039817 -:109A90004944401A0390E00306D453462146179ADE -:109AA000039800F0A9F90544002706E001A85246F2 -:109AB000C05D179990476D1C7F1C4F45F6DBE00396 -:109AC0000CD553462146179A039800F095F90544A2 -:109AD00004E030205246179990476D1C0099481EAB -:109AE00000900029F5DC08E00298029952460078BF -:109AF000491C0291179990476D1CBBF10001ABF115 -:109B0000010BF1DC5BE100F065F90544761C30786F -:109B100000287FF40DAE19B02846BDE8F08F000094 -:109B20000928010030313233343536373839616233 -:109B300063646566000000003031323334353637F7 -:109B4000383941424344454600000000600700D4D4 -:109B5000062708F1070020F00700F0E802238046FE -:109B600003F0004C5FEA0C0001D097A009E020054B -:109B700001D596A005E0E00701D095A001E0AFF285 -:109B80004C001390307823F0004365280CD006DC9D -:109B9000452809D046281DD047287FD13BE06628BC -:109BA00018D067287AD136E00021112F01DB11206F -:109BB00000E0781CCDE9000104A90CA8FFF75CFBCC -:109BC000DDE90D010C9A4FF0000B07F1010910922D -:109BD00000914EE04FF000400097CDE9011004A93C -:109BE0000CA8FFF749FBDDE90D020C9B0F994FF024 -:109BF000000B91461093009211B9791C00EB0109FA -:109C0000B7EB090003D4C0F1FF3B07F10109A9EB51 -:109C10000700019042E0012F00DA01270021112FF7 -:109C200001DD112000E03846CDE9000104A90CA8AF -:109C3000FFF722FBDDE90D010C9A00914FF0000BBC -:109C4000B946109221070FD4009A4A4503DA91468B -:109C500001E0A9F10109B9F1010F05DD109AA9F19F -:109C60000101515C3029F4D0B84202DA10F1040F3E -:109C700003DA0121CDE9011010E0002803DC834460 -:109C8000A9EB000102E0411C494500DD8946A0EB3B -:109C90000B00401C01904FF000400290200705D4BB -:109CA0000198484502DB4FF0FF30019000208DF80D -:109CB0004B0002980DF14B07B0F1004F25D0022068 -:109CC0000C902B200D90029800280CDA4042029054 -:109CD0002D200D9007E00A210298F6F765FC30313F -:109CE000029007F8011D0C99481E0C900029F2DC27 -:109CF00002980028EFD1791E0D980870307800F096 -:109D0000200040F0450007F8020D11A8C01BC01D3F -:109D100002901398007800B1012000EB090101982E -:109D200001EBE071029801440398401A401E039031 -:109D3000E00306D453462146179A039800F05CF8D6 -:109D400005441398007818B15246179990476D1C36 -:109D5000E00323D553462146179A039800F04CF8A8 -:109D600005441BE0BBF1000F07DB0098584504DDFC -:109D70001098179910F80B0001E0179930205246FF -:109D8000904701980BF1010B401E05F10105019070 -:109D900004D12E205246179990476D1CB9F100014D -:109DA000A9F10109DEDC05E017F8010B524617990D -:109DB00090476D1C0299481E02900029F4DC53461E -:109DC0002146179A03989EE62D0000002B00000004 -:109DD000200000002DE9F041044600251E461746EC -:109DE000880404D405E039462020B0476D1C641E69 -:109DF000F9D52846BDE8F0812DE9F041044600255B -:109E00001E469046C80301D5302700E0202788046D -:109E100004D505E041463846B0476D1C641EF9D5AF -:109E20002846BDE8F0810FB410B5BDF80C100298BB -:109E3000F7F77CFA012802D110BC5DF814FB002072 -:109E4000FAE70FB410B5BDF80C1000220298F7F72E -:109E50007FFA10BC5DF814FB0FB410B5BDF80C1000 -:109E600001220298F7F774FA10BC5DF814FB2DE993 -:109E7000FC4704460D4616461F46DDF8288020683C -:109E80000169D1E90401CDE900012068D0F810C0D2 -:109E9000DCF80C904B469CE80700C8472A21206854 -:109EA00000F0F4F9E2892A4491B2206800F017FA30 -:109EB000E2893A4491B2206800F011FA2B2120681F -:109EC00000F0E4F9228A324491B2206800F007FAE7 -:109ED000228A424491B2206800F001FA2C212068C5 -:109EE00000F0D4F9206800F04AF920680169D1E94E -:109EF0000401CDE900012068D0F810C0DCE902932C -:109F00004A46DCE90001C847BDE8FC87816170472B -:109F100030B500220023002401F478052A0A01F458 -:109F20007C456B09C1F3C40442EA030525438582DD -:109F300030BD2DE9FC4104460D46257220680169BB -:109F4000D1E90401CDE9000120680669F7683B46C4 -:109F500096E80700B8475DB93621206800F096F909 -:109F60007021206800F0CCF90020E08120822AE0F6 -:109F7000022D0BD13621206800F088F900212068DD -:109F800000F0BEF90020E08120821CE0012D0CD100 -:109F90003621206800F07AF9A021206800F0B0F99D -:109FA0005020E081002020820DE0032D0BD13621CE -:109FB000206800F06BF9C021206800F0A1F90020B2 -:109FC000E08150202082206800F0D9F820680169E3 -:109FD000D1E90401CDE9000120680669D6E90273E0 -:109FE0003A46D6E90001B847BDE8FC8170B50446A1 -:109FF0000D46E561A888142816D004DC0C2807D08B -:10A00000102823D10AE0182814D020281ED117E0E8 -:10A01000842002590F492046904718E084200259B5 -:10A020000D492046904712E0842002590B492046F2 -:10A0300090470CE08420025909492046904706E0E9 -:10A040008420025907492046904700E000BF00BF26 -:10A0500070BD000020010020140100200801002034 -:10A06000FC000020F00000204A68002A06D00A68A0 -:10A07000531C0B6010704868401E486070472DE903 -:10A08000FC4105460E4600270DB1012100E00021EC -:10A090000846DD21F6F7EEFC2C460CB1012100E06C -:10A0A000002108463621F6F7E5FCA06960B1A169F8 -:10A0B000D1E90401CDE90001D4F818C0DCF80C8026 -:10A0C00043469CE80700C04700BF284602F0AAFEAE -:10A0D0003146284602F0D7FE0746284602F086FEA3 -:10A0E0003846BDE8FC812DE9FC4705460E4617467B -:10A0F0004FF000080DB1012100E000210846F021D9 -:10A10000F6F7B8FC2C460CB1012100E0002108460E -:10A110002821F6F7AFFCA06960B1A169D1E904017B -:10A12000CDE90001D4F818C0DCE902934A46DCE925 -:10A130000001C84700BF284602F074FE002407E073 -:10A140003178284602F09FFE8046761C601C84B25F -:10A15000BC42F5DB284602F049FE4046BDE8FC87DC -:10A160000A68531C0B60107070470FB410B5BDF82F -:10A170000C100298F7F7E2F810BC5DF814FB00BF72 -:10A18000016A0968896801F080010029F8D17047E7 -:10A1900000BF016A0968896801F002010029F8D04E -:10A1A00070472DE9FC4104460E4617462068006AB8 -:10A1B000006800684FF6BF7108402168096A0968A5 -:10A1C00008602068006A0068006840F40060216848 -:10A1D000096A096808602068006A0068006840F041 -:10A1E00040002168096A0968086020680169D1E9AE -:10A1F0000401CDE900012068D0F810C0DCF80C8023 -:10A2000043469CE80700C047002509E036F81500E2 -:10A210002168096A0968C8602068FFF7B9FF6D1CEA -:10A22000BD42F3D32068FFF7AAFF20680169D1E996 -:10A230000401CDE900012068D0F810C0DCE90283F8 -:10A240004246DCE90001C0472068006A00680068F7 -:10A250004FF6BF7108402168096A096808602068E4 -:10A26000006A006800684FF2FF7108402168096ABF -:10A27000096808602068006A0068006840F04000D3 -:10A280002168096A09680860BDE8FC812DE9FC4184 -:10A2900004460D462046FFF772FFE169D1E904014B -:10A2A000CDE90001E669F7683B4696E80700B84744 -:10A2B000206A0068C5602046FFF76AFF2046FFF766 -:10A2C0005EFFE169D1E90401CDE90001E669D6E963 -:10A2D00002733A46D6E90001B847BDE8FC8170B583 -:10A2E00004460D462812216A0968C8602046FFF717 -:10A2F0004FFF206A0068C5602046FFF749FF70BD28 -:10A3000070B504460D46206A0068C5602046FFF718 -:10A310003FFF70BD1CB502F0BDFE054801210023C2 -:10A320008A02CDE9001003A1064803F03DFF1CBDE1 -:10A330007C000020627573696E6573735F7461736E -:10A340006B00000059A3000810B500F0BBF801F045 -:10A3500025F801F0EFF810BD00BF01F0A5F800F0FE -:10A3600039F9002000F000FA4FF47A7003F06CF82D -:10A37000F3E7F0B503460024012901D0022904D1F6 -:10A3800001F10C00C1B2581E83B24D1C05EB45050E -:10A39000052695FBF6F5022606FB012635441D44ED -:10A3A0001846DE1703EB967605EBA605642693FBAD -:10A3B000F6F6AD1B4FF4C87693FBF6F63544072648 -:10A3C00095FBF6F706FB1755ECB2601CC0B2F0BD6A -:10A3D0002DE9F04105460E4618273946002000F0C9 -:10A3E000F1FA04460CB1012100E0002108463621B3 -:10A3F000F6F740FB2560A6800548A0600548E060B0 -:10A4000005482061054860612046BDE8F0810000F4 -:10A41000599E0008439E00086BA10008279E000873 -:10A4200000BFEFF3058008B1012070470020FCE772 -:10A430000FB470B598252946002000F0C3FA0446F1 -:10A440000CB1012100E0002108461C21F6F712FBA7 -:10A45000204604A9382203E011F8013B00F8013B33 -:10A46000131EA2F10105AAB2F6D100BF012184F8A2 -:10A470009410022020B1012803D0022807D101E066 -:10A480000CE00BE004F1380000F03EF906E0204655 -:10A4900000F007F8002070BC5DF814FB00BF2046F8 -:10A4A000F9E710B504460CB1012100E0002108468F -:10A4B0001421F6F7DFFA00BF2146002000F058FA19 -:10A4C00000BF10BD30B5ADB04FF400613D48FFF79F -:10A4D0007FFF29904FF480513A48FFF779FF2C9085 -:10A4E0003822394918A8F5F7FEFE0020049029A863 -:10A4F0000FC88DE80F00012026A90EC902F034FC18 -:10A50000189018983149C26A9047232218A90AA8BE -:10A51000F5F7E9FE9DF883008DF84B00142221A980 -:10A5200013A8F5F7E0FE28220EA96846F5F7DBFE32 -:10A530000AA80FC8FFF77CFF25490861096909B11E -:10A54000012100E0002108464FF48771F6F792FAE6 -:10A550001F4800690068C169D1E90401CDE9000123 -:10A560001B4800690068C469194800690068C0692F -:10A57000856894E80F00A8471548006900680169DC -:10A58000D1E90401CDE900011148006900680469BE -:10A590000F48006900680069856894E80F00A847C3 -:10A5A00000224FF400510748F6F7D2FE084A10691E -:10A5B0001269916B8847012251030248F6F7C8FEE1 -:10A5C0002DB030BD000C0240A8E700085006002066 -:10A5D000E444002030B5A5B0802105A8F5F79CFE25 -:10A5E000334908690969D1F88820324990473049D0 -:10A5F00008690969CA6E002190472D4908690969EF -:10A600000A6E6FF07F41904746242949086909691D -:10A610000A6E2949904726490869096927A32246F5 -:10A620008D6E0D21A8472249086909690A6E2749DC -:10A6300090471F490969C969C98821448AB21C49E0 -:10A640000869096922A38D6E0D21A8471849086978 -:10A6500009690A6E23499047154908690969D1F8C3 -:10A660008420214990471248007B1149C97A104A39 -:10A67000927A0F4BDB79CDE90032CDE902100C481C -:10A680008379808800F5FA6218A105A8FEF7FAFB25 -:10A6900007490969C969C98804EB41018AB20449BB -:10A6A0000869096905AB8D6E0D21A84725B030BD3D -:10A6B000E4440020D8000020FF80800053544D3334 -:10A6C0003220525443B2E2CAD400000080FFFF009F -:10A6D000C6C1C4BBB7D6B1E6C2CA3A3234302A3298 -:10A6E000343000008080FF000801002025642D2503 -:10A6F0003032642D2530326420253032643A2530E2 -:10A7000032643A253032640010B504460CB10121A0 -:10A7100000E00021084640F2AF11F6F7ABF9094816 -:10A720002060094860620948A0620948A06309489E -:10A73000E06409482065094820630948E063094846 -:10A74000606310BD81940008339F0008119F0008CA -:10A750006F9E00080D9F0008ED9F00082D920008D5 -:10A76000378F0008FD93000810B504462CB94FF44C -:10A7700000510348F6F7E2FD00E000BF00BF10BD46 -:10A7800000080240F6F7FCFDFBF728FAF9F790FE07 -:10A79000F9F738FEF9F7A4FFF9F7BCFFF9F766FE01 -:10A7A000F9F7DCFFF9F7B8FF002000F04BF80120C3 -:10A7B00000F048F8FFF7C8FDFFF7ACFDF9F764FEBD -:10A7C00000F033F900BFFEE701460020842901D0E4 -:10A7D000CA1C1044704700002DE9F04104460E46A3 -:10A7E0001548005D38B91448183801682046884774 -:10A7F0000120BDE8F081114850F82400B04219D979 -:10A800000F4850F82400B6FBF0F70B48083850F812 -:10A81000240030F81780002508E000210648083899 -:10A8200050F824007A1920F812106D1C4545F4DB0D -:10A830000020DEE70120DCE7A000002008E8000897 -:10A8400000E8000810B504460C4951F824104A00ED -:10A850000B4951F82400002100F0C8F8094951F8CB -:10A8600024200749083951F82400002100F0BEF8DF -:10A87000012103480830015510BD0000F8E7000829 -:10A880009800002008E800082DE9F04704460F462C -:10A890000025A9462348005D20B9224818380168E0 -:10A8A000204688471FB94FF0FF30BDE8F0871E48AB -:10A8B00050F82400B7FBF0F61B4850F82400B7FB13 -:10A8C000F0F100FB117000B1761C184850F824001C -:10A8D000451E22E01348083850F8240030F81500CF -:10A8E00010B909F1010901E04FF00009B14513D198 -:10A8F0004FF0000809E00B48083850F8240005EB39 -:10A90000080220F8126008F10108B045F3D30648A8 -:10A9100050F824006843C8E76D1E002DDADA4FF0C6 -:10A92000FF30C2E7A000002000E80008F8E70008B8 -:10A9300010B501460023002207E00B4850F8210023 -:10A9400030F8120000B15B1C521C084850F821007E -:10A950009042F2D864205843044C54F82140B0FB94 -:10A96000F4F0C0B210BD000098000020F8E7000825 -:10A970002DE9F04104460D460DB9BDE8F0810F48C0 -:10A9800050F824002E1A0E4850F82400B6FBF0F1BF -:10A990000A48083050F8240030F81100084951F8EE -:10A9A000241000FB01F73A460021284600F01EF86B -:10A9B00031462046FFF710FF00BFDEE79000002081 -:10A9C00000E8000870B504460E4631462046FFF701 -:10A9D0005BFF0546681C08B9002070BD024850F8AE -:10A9E00024002844F9E700009000002030B5034619 -:10A9F00001E003F8011B141EA2F10102F9D130BDE0 -:10AA000070B5044625460DB1294600E001210846EF -:10AA100002F01AFD002070BD10B503F055FC0128AE -:10AA200001D1002010BD0120FCE710B502F0DAFDD5 -:10AA3000002010BD10B5FFF7F3FC10B103F05AFC75 -:10AA400010BD03F051FCFBE7F8B504460D46A068C5 -:10AA500040B1E06830B10020009094E80F0002F0AF -:10AA600059FFF8BD0022D4E9000102F026FFF8E703 -:10AA70002DE9FF4107460D4614460295002001903E -:10AA80003DB9802000909DE8070087E80700BDE8F9 -:10AA9000FF81002003900026601C08B9761E03E0A9 -:10AAA00014B1264606B90126FFF7BAFCB0B103AAD5 -:10AAB00001A9284603F0F0F9012802D110200090E6 -:10AAC00001E0002000900398B8B14FF080500E498B -:10AAD0000860BFF34F8FBFF36F8F0EE0324601A9BE -:10AAE000284603F025F9012802D11020009004E047 -:10AAF0000EB9002000E0402000909DE8070087E8A4 -:10AB0000070000BFC3E7000004ED00E077B581B0A7 -:10AB10000646144600200090254605B90125FFF79A -:10AB20007FFCA8B100236A4602A9304603F082F8F0 -:10AB3000012802D0FF2004B070BD009890B14FF002 -:10AB4000805009490860BFF34F8FBFF36F8F09E052 -:10AB500000232A4602A9304602F098FF012801D0BE -:10AB6000FF20E8E70020E6E704ED00E07FB50446BB -:10AB70000D46606998B1A06988B1B4F90800FFF783 -:10AB800023FE0646D4E90510CDE9006102902B466C -:10AB90002269D4E9001003F039FB039013E0B4F903 -:10ABA0000800FFF711FE064603A8CDE90060238ADE -:10ABB0009AB22B46D4E9001003F0F6FA012802D02D -:10ABC000002004B070BD0398FBE700002DE9F041C0 -:10ABD00005460E461C4807681C480068001D02F028 -:10ABE000F3FA50B91948006890F82C1001208840F9 -:10ABF00017490968814316480160681C38B936B1A5 -:10AC000012480168091D134802F028FB1AE07C195C -:10AC10000E4800684460BC4207D20C480168091D18 -:10AC20000D48006802F000FB0CE008480168091DAF -:10AC30000A48006802F0F8FA09480068844201D224 -:10AC400007480460BDE8F0812800002014000020BF -:10AC50002C000020D00800201C000020180000203C -:10AC60004400002010B5044602F004FB23480068AD -:10AC7000401C224908602248006840B9204804600E -:10AC80000846006801280DD100F0BEF90AE01D4811 -:10AC9000006838B91A480068C06AE16A884201D879 -:10ACA0001748046018480068401C1749086094F869 -:10ACB0002C10012088401549096808431349086091 -:10ACC000E16A01EB8101124A02EB8100211D02F0D1 -:10ACD000C5FA02F0F9FA0B48006868B10848006844 -:10ACE000C06AE16A884207D24FF080500949086083 -:10ACF000BFF34F8FBFF36F8F10BD00002400002003 -:10AD00001400002030000020400000202C00002013 -:10AD1000F407002004ED00E010B516E002F0AAFAF6 -:10AD20000C48C068C468201D02F04EFA0A4800684A -:10AD3000401E0949086009480068401E074908602C -:10AD400002F0C2FA204600F05FF8044800680028CC -:10AD5000E4D110BDBC080020240000202000002009 -:10AD600070B504460D46206C70B1216CE06801445A -:10AD7000E160D4E90210884201D32168E1602846ED -:10AD8000226CE168F5F7AFFA70BD2DE9F041044699 -:10AD90000F4615464FF00008A66B206C48B9206896 -:10ADA00000282CD1A06803F053FB80460020A0604F -:10ADB00025E07DB93946226C6068F5F794FA216C7C -:10ADC000606808446060D4E90101884217D32068B4 -:10ADD000606014E03946226CE068F5F784FA216C73 -:10ADE000E068411AE1602168E068884203D2216C82 -:10ADF000A068411AE160022D01D106B1761E701CD7 -:10AE0000A0634046BDE8F08110B5044694F85100B7 -:10AE100030B9206B02F076FA204602F073FA1AE09D -:10AE200094F85100012803D1204602F06BFA12E099 -:10AE300094F85100022801D1012000E0002050B90F -:10AE400000BF502080F31188BFF34F8FBFF36F8F87 -:10AE500000BF00BFFEE710BD01464A6A22B10A6B7F -:10AE60001268C2F1070000E00020704730B54FF4CF -:10AE70007053174800F007042CB1C01D20F00700E4 -:10AE8000134C041B1B1B0246124C22600024114D64 -:10AE90006C60D018083820F007000F4C20600024A8 -:10AEA0000D4D2D686C600C4D2D682C601146441AB8 -:10AEB0004C60094C24680C60084D4C682C60084DAF -:10AEC0004C682C604FF00044064D2C6030BD0000F3 -:10AED000E4080020500000205800002060000020FE -:10AEE0005C0000206C00002000BFFFF715FF064843 -:10AEF00000680128F9D94FF0805004490860BFF379 -:10AF00004F8FBFF36F8FF0E7F407002004ED00E0F0 -:10AF100010B5044654B10020A06020600021E1601B -:10AF200000231A461946204602F0B0FD10BD2DE957 -:10AF3000F04106460D4617469846069C0DB924601A -:10AF400000E02760E66325640121204602F052FDFF -:10AF5000BDE8F0812DE9FF5F81460E469246DDE9AE -:10AF60000E7B109CAAF10100216B01EB800828F0F8 -:10AF7000070808F0070008B9012000E0002050B9D8 -:10AF800000BF502080F31188BFF34F8FBFF36F8F46 -:10AF900000BF00BFFEE786B1002507E0715D04F148 -:10AFA00034004155705D00B902E06D1C102DF5D3E1 -:10AFB00000BF00214320015502E0002084F8340046 -:10AFC000072F00D30627E76267640020A064201DD6 -:10AFD00002F027F904F1180002F023F92461C7F107 -:10AFE0000700A06164620020E06484F850004946D4 -:10AFF0004046039A00F0BCF92060BBF1000F01D07D -:10B00000CBF80040BDE8FF9F10B5002407E004EB3B -:10B0100084010F4A02EB810002F0F6F8641C072C51 -:10B02000F5D30C4802F0F0F80B4802F0EDF80B48AD -:10B0300002F0EAF80A4802F0E7F80A4802F0E4F8F9 -:10B0400004480949086004480849086010BD000028 -:10B05000F40700208008002094080020A8080020A1 -:10B06000BC080020D0080020180000201C00002090 -:10B0700010B50146164800E0006803688B42FBD318 -:10B080000246436813448B4204D143684C6823440E -:10B09000436001460A464B6813440468A34211D139 -:10B0A0000C4C03682468A34208D04B6804686468A9 -:10B0B00023444B6003681B680B6005E0054B1B686D -:10B0C0000B6001E003680B60884200D0016010BD96 -:10B0D000500000205800002070B5054602F0CAF864 -:10B0E000A86B08B9012400E0002402F0EDF8204626 -:10B0F00070BD70B5054602F0BDF8A86BE96B8842DB -:10B1000001D1012400E0002402F0DEF8204670BDE9 -:10B110000A490968096809B9012100E0002121B143 -:10B120004FF0FF31064A116006E004490968C9681A -:10B13000C868034A41681160704700001800002089 -:10B14000440000200E480068401C08B9012000E0BF -:10B15000002050B900BF502080F31188BFF34F8FFB -:10B16000BFF36F8F00BF00BFFEE700BF502080F32A -:10B170001188BFF34F8FBFF36F8F00BF00BFFEE793 -:10B180007000002070B5044602F074F894F9455040 -:10B1900010E0606A08B9012000E0002038B904F12D -:10B1A000240003F015FA18B102F088F900E003E07A -:10B1B000681E45B2002DECDC00BFFF2084F845007E -:10B1C00002F082F802F056F894F9445010E0206939 -:10B1D00008B9012000E0002048B904F1100003F094 -:10B1E000F7F908B102F06AF9681E45B200E001E023 -:10B1F000002DECDC00BFFF2084F8440002F064F86E -:10B2000070BD00002DE9F04104464FF0000802F047 -:10B2100041FA4948006808B9FFF728FE4748006826 -:10B220002040002870D1D4B1083404F00700B0B138 -:10B2300004F00700C0F10800044404F0070008B956 -:10B24000012000E0002050B900BF502080F3118899 -:10B25000BFF34F8FBFF36F8F00BF00BFFEE7002C1F -:10B2600052D03748006884424ED8364E3046056882 -:10B2700001E02E462D686868A04202D228680028A6 -:10B28000F7D12D48006885423ED0306800F10808AB -:10B29000286830606868001B102819D92F1907F03A -:10B2A000070008B9012000E0002050B900BF50207D -:10B2B00080F31188BFF34F8FBFF36F8F00BF00BFC4 -:10B2C000FEE76868001B78606C603846FFF7D0FEC8 -:10B2D0001B4968680968081A194908600846006827 -:10B2E00019490968884203D2154800681649086060 -:10B2F000124968680968084368600020286013489C -:10B300000068401C1149086003F0AEF908F007001E -:10B3100008B9012000E0002050B900BF502080F3A0 -:10B320001188BFF34F8FBFF36F8F00BF00BFFEE7E1 -:10B330004046BDE8F0810000580000206C0000206D -:10B340005C0000205000002060000020640000200D -:10B350000648006830B10549096801F14800896C68 -:10B36000491C01600148006870470000140000207B -:10B37000001F4FF080730360001F21F00103036082 -:10B38000001F054B036014380260001F6FF00203BA -:10B39000036020387047000045B100083EB5002426 -:10B3A000002000F035F884B245F2500084422CD0E1 -:10B3B000401C844229D01920ADF8040001208DF8EA -:10B3C00006008DF807009DF807209DF80610BDF8CF -:10B3D000043003F5FA6398B2FEF7CBFF8DF808004E -:10B3E00000208DF800008DF801008DF8020000218A -:10B3F000009800F037F8DDE9010100F013F845F29C -:10B400005101002000F07AF800BF01203EBD00008D -:10B4100001460022024800EB8102106870470000DC -:10B420005028004003B581B09DF806008DF801005A -:10B430009DF807008DF80200BDF80400C0B28DF839 -:10B4400003009DF808008DF80000002269460448BA -:10B45000F7F7DCFC08B901200EBD0020FCE7000076 -:10B46000EC04002013B586B00C469DF818008DF84A -:10B4700004009DF819008DF805009DF81A008DF85C -:10B4800006008DF80740002004900590002201A9D5 -:10B490000448F7F71BFD10B9012008B010BD0020CB -:10B4A000FBE70000EC04002000B587B0002201A9F2 -:10B4B0001048F7F70DFC002206A90E48F7F7E2FB4B -:10B4C0009DF804000C4988729DF805100A48C17265 -:10B4D0009DF8061001739DF8181001729DF819105F -:10B4E00081719DF81A10C1719DF81B000249888076 -:10B4F00007B000BDEC040020E444002070B5044611 -:10B500000D46F6F727FF2A4621460248F7F7B0FB1B -:10B5100070BD0000EC04002010B588B069460448F6 -:10B52000F7F7B2FE04460CB108B010BD00BFFBE750 -:10B53000F844002010B50E480E490860002048600D -:10B5400000210C488160C160016141610421816179 -:10B55000F7F7BFFE08B1F5F73DFB4FF40061054872 -:10B56000F7F748FD08B1F5F735FBFFF7D5FF10BD3C -:10B57000002C0140F84400200146002009E0074A61 -:10B5800052F820201AB9054A42F820107047421C90 -:10B5900010B20528F3DB00BFF8E700009811012086 -:10B5A00010B504460121204600F075F810BD0000DA -:10B5B00010B50446226891682069F4F7BFFE60B9AF -:10B5C00094F8600020F00100401C84F860000848F6 -:10B5D0000168204601F066FB04E00548416B204607 -:10B5E00001F060FB0020A0810021E18110BD00007E -:10B5F000240200200246087858B1487800F00F0075 -:10B60000082806D0106878B1087813681B781840AD -:10B6100050B192F8600000F0010018B94878C0F30A -:10B62000001008B1002070474FF0FF30FBE700002A -:10B6300010B500F01BFB044624B10348816B204683 -:10B6400001F030FB10BD00002402002070B504465C -:10B65000A189E089081A05B205E02021204601F001 -:10B660003BFA681E05B2002DF7DC217B204600F076 -:10B670007FF870BD10B500F0F9FA044614B1204609 -:10B6800000F054FD10BD10B504464FF0FF312046C8 -:10B6900000F001F810BD2DE9F04104460D46681C8C -:10B6A00008B9012000E000200746E08908B9012D13 -:10B6B00005D0E089A189884203D1681C08B9BDE89A -:10B6C000F081E089A189884210D1012D0ED1E08955 -:10B6D000401EE081A089401EA0810021A28920692E -:10B6E00081540121204600F043F83FE038460AE04B -:10B6F000E18901442269525CE1890144491E2369C0 -:10B700005A54411C08B2A289E189511A8142EFDCE6 -:10B71000A089401EA08137B9E089401EE081082140 -:10B72000204601F0D9F90021A28920698154E089DD -:10B7300006B206E02069815D204601F0CDF9701C5B -:10B7400006B2A089B042F5DC2021204601F0C4F900 -:10B75000A189E089081A401C06B205E008212046AC -:10B7600001F0BAF9701E06B2002EF7DC00BFA6E7A2 -:10B7700070B505460C4603E004A1284601F092FA94 -:10B78000201EA4F10101CCB2F6D170BD0820080042 -:10B7900010B504464FF0FF31204600F041FB10BDCC -:10B7A00010B50446204600F005F80121204601F0BE -:10B7B000FFF910BD70B50446A08900B970BD002125 -:10B7C000A2892069815494F8600000F0010010B350 -:10B7D000204600F086FB204600F0DEFD0021E181DE -:10B7E000A181E08E00B9E9E70DA1204601F05AFAE7 -:10B7F00000232046A26D616900F077FE054625B161 -:10B800002946204600F018FE04E0064881692046DB -:10B8100001F048FA02E02046FFF7CAFE00BFCDE77C -:10B820000D0A00002402002010B502461146002037 -:10B830000B78302B07D14B78782B02D04B78582BD4 -:10B8400001D103200EE00B78302B07D14B78622B0F -:10B8500002D04B78422B01D1012003E00B78302B32 -:10B8600000D1022006E00B782E2B03D14B780BB1D0 -:10B87000042003E011F8014B002CF4D100BF10BDEF -:10B8800002461378272B01D1531C00E013461946BA -:10B8900000200B785C2B1AD14B786E2B0ED004DC79 -:10B8A000302B0FD0622B0FD104E0722B04D0742BFD -:10B8B0000AD105E0082009E00D2007E00A2005E094 -:10B8C000092003E0002001E0487800BF00E008788C -:10B8D000704700002DE9F84F05464FF0000A4FF081 -:10B8E0000A0B2C4600200090012600279FED330A0A -:10B8F00010EE109A804628782D2800D1B61E711CB3 -:10B9000009B9012100E000214819FFF78DFF8246A7 -:10B91000BAF1010F0FD0BAF1020F07D0BAF1030F3D -:10B920000ED14FF0100B022000900AE04FF0080BF0 -:10B930000120009005E04FF0020B0220009000E093 -:10B9400000BF00BF00982918701C08B9012000E052 -:10B9500000200C1811E020782E2803D14FF00108A8 -:10B96000641C0AE0207800F025F907FB0B0708EBC0 -:10B9700088004FEA4008641C00BF20780028EAD104 -:10B98000BAF1040F17D1B8F1000F14D000EE107AFD -:10B99000B8EE401A00EE108AB8EE400AC1EE000A76 -:10B9A00000EE106AB8EEC00A20EE800A10EE109A7F -:10B9B0004846BDE8F88F07FB06F0FAE700000000F4 -:10B9C0002DE9F04107460C4616461D4626B1207863 -:10B9D00024282FD1607868B32078272808D1607890 -:10B9E00030B12046FFF74CFF28600020BDE8F08111 -:10B9F00020782D2805D02078302808DB20783928B9 -:10BA000005DC2046FFF766FF28600020EEE720787F -:10BA1000242807D1607828B12A462146384600F00C -:10BA200031F8E3E7207828B1204600F006F82860D6 -:10BA30000020DBE74FF0FF30D8E770B5044625461D -:10BA400000262078222802D1601C0446054613E017 -:10BA500028785C2805D12846FFF712FFA0556D1CF9 -:10BA600007E02878222802D10020A05501E028789C -:10BA7000A0556D1C701C86B228780028E8D1A0550E -:10BA8000204670BD2DE9F04104460D4616460023C0 -:10BA9000691C2046A26D00F028FD07463FB13946DB -:10BAA000204600F0FDF830600020BDE8F0814FF046 -:10BAB000FF30FAE72DE9F0478CB080460C4615467A -:10BAC0001E464FF0000A202104A8F4F725FCA078B8 -:10BAD00000F00F01681E814203DDA07800F00F0026 -:10BAE00000E0681E07464FF0000912E004A800EBD2 -:10BAF000890309F1010056F8201000224046FFF7A3 -:10BB00005FFF20B14FF0FF300CB0BDE8F08709F1C6 -:10BB10000109681E4845E9DC082F45D2DFE807F037 -:10BB200004080E151C232C37A068804782463EE08F -:10BB3000D4F808900498C847824638E0D4F80890B2 -:10BB4000DDE90401C847824631E0D4F8089004A832 -:10BB500007C8C84782462AE0D4F8089004A80FC84E -:10BB6000C847824623E0D4F808900898009004A8BB -:10BB70000FC8C84782461AE0D4F80890DDE90801EA -:10BB8000CDE9000104A80FC8C84782460FE0D4F8E9 -:10BB90000890DDE908120A98CDE90012029004A885 -:10BBA0000FC8C847824602E04FF0FF3A00BF00BF0F -:10BBB0005046A9E70146302905DB392903DCA1F10C -:10BBC0003000C0B27047612905DB662903DCA1F1B2 -:10BBD0005700C0B2F6E7412905DB462903DCA1F195 -:10BBE0003700C0B2EEE70020ECE70146487800F0ED -:10BBF0000F00012801DCC8687047487800F00F008A -:10BC0000072801DCC868F7E7487800F00F0008282B -:10BC100001DCC868F0E7C868EEE7000010B504462C -:10BC2000002004E03021104A1154411CC8B20928F8 -:10BC3000F8DB607800F00F00012801DC606810BDBF -:10BC4000607800F00F00072801DC6068F7E7607893 -:10BC500000F00F00082801DC6068F0E70249606826 -:10BC600000F005FF0048EAE7AC110120002111E0D7 -:10BC70000A4850F8210058B1084850F8210090F8BF -:10BC80006000C0F3400018B1044850F8210070472C -:10BC9000481C01B20529EBDB0020F8E798110120D0 -:10BCA0002DE9F04107460C460026607800F00F00B1 -:10BCB000801E06281BD2DFE800F003060A0D0E10D6 -:10BCC000A068066814E0A068B0F9006010E0A06801 -:10BCD00006780DE000BFA6680AE0A06845681DB1BF -:10BCE000A1680868A84700E00020064600E000BF01 -:10BCF00000BF3046BDE8F0812DE9F0470446884694 -:10BD0000B8F1000F01D1BDE8F0872046E16E884709 -:10BD100018274FF00009208F00F47F4018B100274A -:10BD20006FF0FF090EE0A06B00F47F0018B1082748 -:10BD3000DFF8BC9006E0A06B00F07F4010B1102748 -:10BD40004FF07F49A66D00253EE006EB05104078D8 -:10BD500000F00F00092835D106EB05112046FFF74A -:10BD600049FC70BB06EB0510406800EA0900A16BB6 -:10BD7000884227D106EB05104168FF20B8400840F3 -:10BD800008FA07F188421DD108FA07F1A06B0843B1 -:10BD9000A0634FF0000847B106EB05104068A7F11B -:10BDA0000801FF228A40104058B906EB0510806850 -:10BDB00020B106EB05108168204688470021A16369 -:10BDC00006E0FFE7681C05B25C20005BA842BCDC13 -:10BDD00000BFB8F1000F05D00021A1634146204605 -:10BDE00000F0CCFA2046216F884700BF8BE70000A7 -:10BDF0000000FFFF70B504460D46FFF737FF06460B -:10BE000006B970BD012C03D1304600F089F905E078 -:10BE1000012C03DD3046696800F094FE00BFF0E7B6 -:10BE200070B504460D46002D25DDB4F9541054209C -:10BE3000005B401E02B2542002535020025B52208D -:10BE4000005B824202DD5020005B01E05220005B7B -:10BE5000404281421DDC5020015B5220005B814248 -:10BE600002DD5020005B01E05220005B404201B245 -:10BE7000542001530DE0002D0ADA5420005B401CD1 -:10BE800001B254200153002903DD0021015370BD8C -:10BE9000FDE72046FFF7DAFB5420005B18B90021CC -:10BEA000A181E1811BE05220005B401DB4F95410D8 -:10BEB0000844052190FBF1F201FB120104F13C0062 -:10BEC00050F821603146206900F000FDA08100B9E2 -:10BED000DDE7A189E1812046216900F0E3FE00BF92 -:10BEE000D5E710B504460021542001535020005BD3 -:10BEF000002810DD5222125B21690AB9052201E0F7 -:10BF00005222125B521E04F13C0353F82200F4F754 -:10BF100015FA00B910BD5222135B04F13C0252F82D -:10BF20002300216900F0D2FC28B15220005B401CA4 -:10BF300081B2522001535020005B401C81B250203E -:10BF40000153052901DD052101535220005B05281D -:10BF500002DB00215220015300BFDBE72DE9F04155 -:10BF600004460D4616460020A0810021E181206094 -:10BF700094F8600020F00100401C84F86000256106 -:10BF8000062096FBF0F0A086542001535020015368 -:10BF900052200153002009E0A28E411C02FB0152F5 -:10BFA00004F13C0141F82020411C08B20528F3DBD4 -:10BFB0000E48A0650E480D49401AC0F30F115C20D1 -:10BFC00001532046FFF7D8FA00230AA12046A26DAC -:10BFD00000F08BFA07463946204600F0C3FA0121EB -:10BFE000204600F0E5FDBDE8F08100001C5401088A -:10BFF0003C5501086C6574746572000070B50446A8 -:10C000000D46A189A08E401E81420DDB3848416853 -:10C01000204600F047FE0121204600F0C9FD2046E1 -:10C02000216900F03FFE70BDE089A189884218D1E6 -:10C03000A189481CA081206945540021A28920695A -:10C040008154E089401CE08194F8600000F0010018 -:10C0500008B1284600E02A200146204600F03CFDB9 -:10C0600044E0E089A189884240DAA289E189511A35 -:10C0700008B20AE0E1890144491E2269525CE18963 -:10C08000014423695A54411E08B20028F2DCE189B8 -:10C09000481CE081206945540021A089401C80B2E1 -:10C0A0002269A0811154E089401E06B20EE094F886 -:10C0B000600000F0010010B12069805D00E02A20DE -:10C0C0000146204600F008FD701C06B2A089B0426F -:10C0D000EDDCA189E089081A06B205E008212046B6 -:10C0E00000F0FAFC701E06B2002EF7DC00BF9AE7E3 -:10C0F0002402002010B5FFF7B9FD044614B1204614 -:10C1000000F0B8F810BD10B50446E089002806DD3F -:10C110000821204600F0E0FCE089401EE08110BDCF -:10C1200010B50446204600F001F810BD70B5054674 -:10C13000AE6D10488168284600F0B4FD002413E07D -:10C1400006EB0410407800F00F0001280ADC06EB33 -:10C1500004112846FFF74EFA20B906EB04112846D1 -:10C1600000F00AF8601C04B25C20405BA042E7DCEF -:10C1700070BD0000240200202DE9F04107460C4666 -:10C180002046FFF74BFD05462946384600F08AFD5C -:10C19000C0F1160006B2002E01DD304600E004209A -:10C1A000064600BF2021384600F096FC701E00B203 -:10C1B000061EF7D1607800F00F00012805DC2A4840 -:10C1C000016C384600F06EFD25E0607800F00F004D -:10C1D000072805DC2448416C384600F063FD1AE06E -:10C1E000607800F00F00082805DC1F48816C384695 -:10C1F00000F058FD0FE0607800F00F00092805DC22 -:10C200001948C16C384600F04DFD04E01648016D38 -:10C21000384600F047FD15A1384600F043FD0725DC -:10C220000DE020780122AA40104008B1782000E0FB -:10C230002D200146384600F04FFC681E45B2002D07 -:10C24000EFDA0AA1384600F02DFD2046FFF7CDFCBD -:10C2500005462946384600F047FC05A1384600F05F -:10C2600021FDBDE8F0810000240200202020000014 -:10C270000D0A000070B50646B56D13484169304699 -:10C2800000F010FD00241AE005EB0410407800F0E7 -:10C290000F00082811DD05EB0410407800F00F00B6 -:10C2A00009280ADC05EB04113046FFF7A3F920B991 -:10C2B00005EB04113046FFF75FFF601C04B25C2001 -:10C2C000805BA042E0DC70BD2402002070B5064611 -:10C2D000B56D13480169304600F0E4FC00241AE013 -:10C2E00005EB0410407800F00F00072811DD05EB86 -:10C2F0000410407800F00F0008280ADC05EB041158 -:10C300003046FFF777F920B905EB04113046FFF707 -:10C3100033FF601C04B25C20805BA042E0DC70BD97 -:10C320002402002070B50646B56D1348C16830463A -:10C3300000F0B8FC00241AE005EB0410407800F08F -:10C340000F00012811DD05EB0410407800F00F000C -:10C3500007280ADC05EB04113046FFF74BF920B93A -:10C3600005EB04113046FFF707FF601C04B25C20A8 -:10C37000805BA042E0DC70BD2402002070B5044662 -:10C380000D4694F8600020F0040084F8600029460F -:10C390002046FFF733FE70BD18B504460820009014 -:10C3A000A189202304F11402206900F0EDF9E08650 -:10C3B00018BD70B5044600252BE004F1140050F8B8 -:10C3C0002500007822280CD1002104F1140050F837 -:10C3D0002500017004F1140050F82510491C40F8A4 -:10C3E000251004F1140151F82500F3F7A0FF86B2DF -:10C3F00004F1140050F82510701E085C222806D1A4 -:10C40000002104F1140050F82520701E1154681CFE -:10C4100085B2E08EA842D0DC70BD10B50446E0893C -:10C42000A189884207DAE289501CE0812069815C99 -:10C43000204600F051FB10BD2DE9F04104460D46A9 -:10C44000002694F8600020F00200801C84F8600050 -:10C45000687800F00F0088B92046FFF7AAFFAF68A0 -:10C46000E08E04F11401B84706466878C0F3401026 -:10C4700018B93146204600F0CFFB2DE0687800F077 -:10C480000F00012810D1E28E04F114032946204642 -:10C49000FFF710FB06466878C0F34010E0B931465C -:10C4A000204600F0B9FB17E0687800F00F00022882 -:10C4B00009DB687800F00F00072804DC29462046D5 -:10C4C00000F002F908E0687800F00F00082803D1B6 -:10C4D0002946204600F046F894F8600020F002005B -:10C4E00084F860003046BDE8F0812DE9F04706464B -:10C4F000884614461F465C20805BB16D611AA0EB34 -:10C5000011101FFA80F9002528E004EB051040788F -:10C5100000F00F00092805D004EB05113046FFF7A5 -:10C5200069F800B118E004EB0510FFF777FB8246CD -:10C5300047B951464046F3F701FF60B904EB0510D7 -:10C54000BDE8F0873A4651464046F3F705FF10B97B -:10C5500004EB0510F4E700BF681C85B24D45D4DB41 -:10C560000020EDE770B504460D462560A86858B177 -:10C57000A868F3F7DCFE38B1E08E022806DBA1697B -:10C58000A868F3F7DBFE08B9012000E0002094F86A -:10C59000601060F3000184F860100848816B204649 -:10C5A00000F080FB94F8600000F0010020B1034827 -:10C5B0000168204600F076FB70BD000024020020D8 -:10C5C0002DE9F04106460F46FFF750FB054615B929 -:10C5D0000020BDE8F081002331462846AA6DFFF710 -:10C5E00084FF044634B91148816A284600F05AFB9A -:10C5F0000020EEE7607800F00F00022804DB60788E -:10C6000000F00F0007280ADD3146284600F04AFBFB -:10C610000648416A284600F045FB0020D9E73A4623 -:10C620002146284600F004F8D3E700002402002049 -:10C630002DE9F04106460C4615466078C0F380109F -:10C6400028B12048016A304600F02CFB34E06078C5 -:10C6500000F00F00801E06282CD2DFE800F0030651 -:10C660000A0D1218A068056025E029B2A0680180B3 -:10C6700021E0A06805701EE02946A06800F026F9B8 -:10C6800019E01048C169304600F00CFB13E0A068C7 -:10C69000806870B1A068006830B1A0688768A16840 -:10C6A00008682946B84704E0A06887682846B84764 -:10C6B00000BF00E000BF00BF2146304600F004F894 -:10C6C000BDE8F08124020020FEB505460C4626A2F6 -:10C6D00007CA8DE8070021462846FFF7E1FA07461A -:10C6E0002846616800F0DEFA22A1284600F0DAFA56 -:10C6F000607800F00F0005280CD11FA1284600F03B -:10C70000D1FA3946284600F0CDFA1BA1284600F0A0 -:10C71000C9FA21E06946384600F07EF9C0F10B0005 -:10C72000694646183146284600F0BCFA13A128464F -:10C7300000F0B8FA002004E030210DF80010411C90 -:10C7400008B20B28F8DB6946384600F090F96946D4 -:10C75000284600F0A7FA00BF00BF0AA1284600F053 -:10C76000A1FA3846FEBD0000303030303030303075 -:10C7700030303000203D2000220000002C20307896 -:10C78000000000000D0A00002DE9FF4F04468C4612 -:10C7900015460D9F4FF00108002000900190029077 -:10C7A00003900021002600BF04E0002245F820206D -:10C7B000421C10B2B842F8DB002068E011BB225CDA -:10C7C0009A420DD0B8F1010F0AD1BE4208DA04EB4B -:10C7D000000A3246761C45F822A04FF0000811E00E -:10C7E000225C9A4202D0225C202A0BD1B8F1000FC1 -:10C7F00008D100222254421CA25C202A01D04FF012 -:10C80000010842E0002234E0002918DD14F800900D -:10C81000DFF888A00AEB420A9AF801A0D1450ED1B0 -:10C82000A1F101091DF80990DFF870A01AF812A013 -:10C83000D14504D1A1F1010909F0FF011BE014F871 -:10C840000090DFF858A01AF812A0D1450DD1DFF8FA -:10C850004C9019F812B0894601F1010A0AF0FF0163 -:10C860000DF809B001F00F0105E002F1010909F02E -:10C87000FF02002AC8D000BF225C5C2A04D1421CFF -:10C88000A25C0AB1421C90B200BF421C90B260454B -:10C8900094DB304604B0BDE8F08F00007802002041 -:10C8A00030B502460B460020002108E0545C5D5C78 -:10C8B000AC4200D008E0441CA0B24C1CA1B2545CB5 -:10C8C00014B15C5C002CF1D100BF30BD02460020E9 -:10C8D00003E00B5C1354431C98B20B5C002BF8D1A3 -:10C8E000135470472DE9F84F0446B4F834A04FF0C4 -:10C8F00000080025A08938B92046FFF711FC012166 -:10C90000204600F055F970E0A08900286DDD002177 -:10C91000A28920698154A66D002737E006EB071134 -:10C920002046FEF767FE78BB06EB0710FFF776F9A7 -:10C93000834659462069FFF7B3FFA189884223D176 -:10C94000F5B1012D03D12AA1204600F0ABF906EB89 -:10C9500008112046FFF710FC06EB0710FFF75EF901 -:10C96000834606EB0810FFF759F959460090FFF788 -:10C9700097FF8146CA4501DD484600E050468246A1 -:10C980001FFA87F8681C85B2781C07B25C20005B30 -:10C99000B842C3DC0DB9BDE8F88F012D02D12046A5 -:10C9A000FEF754FE4DB106EB0810FFF737F90746C6 -:10C9B00039462069FFF78AFFA081012D0ADD06EBC9 -:10C9C00008112046FFF7D8FB0121204600F0F0F8BF -:10C9D000A4F80CA00021A28920698154A189E181D9 -:10C9E0002046216900F05EF900BF00BFD3E70000D8 -:10C9F0000D0A000008B505462C460CE0606E50B1EB -:10CA000001216846626E9047012804D19DF800100C -:10CA10002046FFF771F9F1E730B502460B241346C3 -:10CA2000002A00DA53420020C8720DE00A2093FB6E -:10CA3000F0F500FB15303030C5B2601EC0B20446C0 -:10CA40000D540A2093FBF0F3002BEFD1002A04DAF7 -:10CA50002D25601EC0B204460D5422B93025601E3B -:10CA6000C0B204460D54C4F10B0040B230BD30B525 -:10CA700002460B460824002018720EE002F00F0157 -:10CA8000092902DD01F1570001E001F13000C5B2D2 -:10CA9000601EC0B204461D541209002AEED1C4F132 -:10CAA000080040B230BD10B5044601212046FFF712 -:10CAB000B7F910BD10B5FFF7D9F8044614B12046F8 -:10CAC000FFF704FC10BD10B5FFF7D0F8044614B111 -:10CAD0002046FFF727FC10BD13B50446012101A82D -:10CAE000A26E90471CBD00002DE9F04104460F46A0 -:10CAF00000253E46A06E10B90020BDE8F08102E09E -:10CB0000761C681C85B2307828B130780D2802D0A8 -:10CB100030780A28F4D1242D08DD24213846A26E6D -:10CB20009047032106A0A26E904703E029463846AD -:10CB3000A26E9047242D01DD2420DEE72720DCE7CC -:10CB40002E2E2E002DE9F04104460E4600233146DC -:10CB50002046A26DFFF7C9FC0546EDB11248C16A37 -:10CB6000204600F09FF82846FFF758F80746394658 -:10CB7000204600F097F80DA1204600F093F82846D3 -:10CB8000FFF733F807463946204600F08BF807A137 -:10CB9000204600F087F804E003488169204600F051 -:10CBA00081F8BDE8F0810000240200200D0A000099 -:10CBB00070B504460D4694F8600000F00100D8B14D -:10CBC0001DB110A1204600F06DF820684168204694 -:10CBD00000F068F80CA1204600F064F8A06808B1E5 -:10CBE000A06800E009A00146204600F05BF808A11B -:10CBF000204600F057F804E00648016B204600F09C -:10CC000051F870BD0D0A00003A0000002F0000002E -:10CC10002420000024020020FEB505460C4618A280 -:10CC2000D2E900109268CDE90102009117A12846CF -:10CC300000F038F869462046FFF7EEFEC0F10B0021 -:10CC4000694646183146284600F02CF812A12846BD -:10CC500000F028F8002004E030210DF80010411CFD -:10CC600008B20B28F8DB69462046FFF700FF69464B -:10CC7000284600F017F80AA1284600F013F8FEBD78 -:10CC800030303030303030303030300052657475F4 -:10CC9000726E3A20000000002C2030780000000066 -:10CCA0000D0A00002DE9F04104460D4600262F46EE -:10CCB000A06E10B90020BDE8F08101E0701C86B2C2 -:10CCC00017F8011B0029F9D131462846A26E90477A -:10CCD00080B2F0E7F0B51E49896B09684968C1F573 -:10CCE000807188B21B490988884203DB1949098889 -:10CCF000411A04E017490988C1F5807101448BB2DB -:10CD0000002120E0134E36887218D61702EB166603 -:10CD10003612A2EB0626104FBD5D104E3688721CEF -:10CD2000D61702EB5666F611A2EBC616B4B20C4A41 -:10CD30001288944205D00B4A084E36889555074A0A -:10CD400014804A1C91B29942DCDB02490880F0BD94 -:10CD5000A8060020840200202C140120800200205C -:10CD6000820200202C1501200FB42DE9F041054668 -:10CD70000E9F022D01DA012100E0002108464FF448 -:10CD80008771F3F777FE342631460020FDF71AFE4F -:10CD9000044600BF201D07A91C2203E011F8013B37 -:10CDA00000F8013B131EA2F10106B2B2F6D100BF9A -:10CDB000278084F830500A49E1625DB1012D04D129 -:10CDC000084860620849A16204E040F21F11002097 -:10CDD000F3F750FE2046BDE8F0015DF814FB0000BB -:10CDE0003D9400087FA00008E7A000087CB5044639 -:10CDF0000CB1012100E0002108464421F3F73AFE7E -:10CE0000206970B12169D1E90401CDE900012569EA -:10CE1000D5E902633246D5E90001B047204600F06B -:10CE20001CF87CBD7CB504460CB1012100E000215A -:10CE300008465321F3F71EFE206968B12169D1E944 -:10CE40000401CDE900012569EE68334695E8070045 -:10CE5000B047204600F001F87CBD70B504460025BF -:10CE60000CB1012100E0002108460D21F3F702FE7C -:10CE70002588002D06DD00E000BF281EA5F1010178 -:10CE80008DB2F9D170BD2DE9F34182B00446FF2780 -:10CE90000CB1012100E000210846A921F3F7EAFDC9 -:10CEA00094F8310001287ED100269AE025460DB184 -:10CEB000012100E0002108468C21F3F7DBFDE86842 -:10CEC00060B1E968D1E90401CDE90001D5F80CC0F1 -:10CED000DCF80C8043469CE80700C04700BF2046B2 -:10CEE000FFF7BBFF9DF80C0000F08000C8B125469D -:10CEF0000DB1012100E0002108466221F3F7BAFDDF -:10CF0000686860B16968D1E90401CDE90001D5F82C -:10CF100004C0DCE902834246DCE90001C04700BFEF -:10CF200019E025460DB1012100E0002108467021DD -:10CF3000F3F7A0FD686860B16968D1E90401CDE943 -:10CF40000001D5F804C0DCF80C8043469CE80700DB -:10CF5000C04700BF00BF2046FFF77FFF25460DB149 -:10CF6000012100E0002108467E21F3F783FDE868F7 -:10CF700060B1E968D1E90401CDE90001D5F80CC040 -:10CF8000DCE902834246DCE90001C04700BF2046DD -:10CF9000FFF763FF9DF80C004006000E0390780633 -:10CFA000070EA06800E023E00068C0B125460DB17F -:10CFB000012100E0002108469A21F3F75BFDA968F2 -:10CFC000D1E90401CDE90001D5F808C0DCF81480EE -:10CFD0009CE80F00C047012801D1781CC7B2701C23 -:10CFE000C6B2082EFFF662AF384604B0BDE8F08145 -:10CFF000002001904FF4FA600090012301AA03A9D8 -:10D00000206AF6F79BFC08B1FF20EEE79DF80400CC -:10D01000EBE700000FB4F8B507A800904FF40061EB -:10D020001348009B069AFBF741FF0546002000903D -:10D030000326104890F89C02032812D10D48D0F81E -:10D04000BC72F4F78BF9044605E0F4F787F9001B8E -:10D05000B04200D903E0D7F814020028F5D100BF90 -:10D0600000BFA9B20248F3F7E9FCF8BC5DF814FB75 -:10D070006C02012090F5002070B505460C46214653 -:10D0800001A0FFF7C7FF70BD6C656E203D202564D1 -:10D090000D0A00001CB5012000F0FEFB14490860D9 -:10D0A000144815498866154848661548C8661548E5 -:10D0B00008674FF4007214490F48FEF74FFF4FF412 -:10D0C000807212491248F7F7EFF811480068C068FB -:10D0D00040F010000E490968C86000200121064B8D -:10D0E0008A02CDE900100BA10D4801F05DF81CBDCE -:10D0F0007C020020ADD10008B81101203DD100080C -:10D1000025D1000891D100082C1201202C140120F7 -:10D11000A80600207368656C6C5F7461736B000017 -:10D12000F5C9000810B504464FF0FF310248006809 -:10D1300000F018FF002010BD7C02002030B5024630 -:10D140000B46002119E00F4800880F4C2488A042AC -:10D1500000D114E00D480C4C2488055D08464C1C99 -:10D16000A1B21554084C2488601CC41700EB546409 -:10D17000E411A0EBC414044D2C809942E3DB00BF02 -:10D1800008B230BD80020020820200202C15012050 -:10D1900010B5044600231A4619460348006800F0FB -:10D1A00075FC002010BD00007C02002070B5054613 -:10D1B0000C4640F2FF13224629460248F7F797F83B -:10D1C00020B270BDA806002001460A69D1E90130ED -:10D1D0009860D1E9010358605068884201D188689D -:10D1E0005060002008611068401E10601068704791 -:10D1F000034B0360034B0B608023136070470000F8 -:10D2000098020020EC02002000F1080141604FF07C -:10D21000FF31816000F10801C160016100210160FE -:10D22000704700210161704710B502460B685C1C15 -:10D230000CB9106907E002F1080000E0406844689A -:10D2400024689C42FAD944684C604C68A1608860AC -:10D2500041600A611468641C146010BD42684A6031 -:10D2600093688B60936859609160086103685B1CE8 -:10D270000360704700BF502080F31188BFF34F8FC9 -:10D28000BFF36F8F00BF0E480068401C0C49086058 -:10D2900008460068012812D10A480068C0B208B9DF -:10D2A000012000E0002050B900BF502080F3118819 -:10D2B000BFF34F8FBFF36F8F00BF00BFFEE7704714 -:10D2C0007000002004ED00E00D48006850B900BF78 -:10D2D000502080F31188BFF34F8FBFF36F8F00BFD3 -:10D2E00000BFFEE706480068401E05490860084682 -:10D2F000006820B9002080F3118800BF00BF70478C -:10D300007000002070B506463546002E44D0083D1A -:10D310002C46224960680968084008B1012000E0F5 -:10D32000002050B900BF502080F31188BFF34F8F09 -:10D33000BFF36F8F00BF00BFFEE7206808B9012070 -:10D3400000E0002050B900BF502080F31188BFF3E7 -:10D350004F8FBFF36F8F00BF00BFFEE70F496068BC -:10D3600009680840C0B12068B0B90C496068096814 -:10D370008843606000F08EF90949606809680844D4 -:10D38000074908602046FDF773FE06480068401C08 -:10D390000449086001F068F970BD00006C000020CD -:10D3A0005C0000206800002000204FF0E0210861B0 -:10D3B0008861064800684FF47A71B0FBF1F0401EB6 -:10D3C0004FF0E021486107200861704710000020FD -:10D3D00070B5F2F741FF0446102C16D304F1E0209B -:10D3E00090F8F05315480078854201DB012000E0F9 -:10D3F000002050B900BF502080F31188BFF34F8F39 -:10D40000BFF36F8F00BF00BFFEE70D48006800F458 -:10D41000E0600C490968884201D8012000E0002042 -:10D4200050B900BF502080F31188BFF34F8FBFF376 -:10D430006F8F00BF00BFFEE770BD000074000020CA -:10D440000CED00E07800002070B504460025D4B152 -:10D450001248006808B9012000E0002050B900BF60 -:10D46000502080F31188BFF34F8FBFF36F8F00BF41 -:10D4700000BFFEE700F00EF900212046FDF7A6FBF5 -:10D4800001F0F2F805463DB94FF0805004490860BC -:10D49000BFF34F8FBFF36F8F70BD00004C000020B3 -:10D4A00004ED00E00349096801600349096841602F -:10D4B000704700003C0000202800002001200149A6 -:10D4C000086070473800002070B504460D4654B916 -:10D4D00000BF502080F31188BFF34F8FBFF36F8FD1 -:10D4E00000BF00BFFEE70548016818312046FFF77E -:10D4F0009BFE01212846FDF769FB70BD140000204A -:10D500002DE9F04706460F4634464FF00109002E3C -:10D5100060D0A06C50B900BF502080F31188BFF3D9 -:10D520004F8FBFF36F8F00BF00BFFEE7606CB84244 -:10D5300001D23D4600E0656CE06AA8424AD0A06C8A -:10D54000012847D124480068844201D0012000E02E -:10D55000002050B900BF502080F31188BFF34F8FD7 -:10D56000BFF36F8F00BF00BFFEE7D4F82C80E562E9 -:10D57000A06900F0004010B9C5F10700A06108EBF8 -:10D580008801164A02EB81016069884201D10120BD -:10D5900000E00020F0B1201DFFF716FE40B994F81E -:10D5A0002C10012088400E49096881430C48016015 -:10D5B00094F82C100120884009490968084308495B -:10D5C0000860E16A01EB8101044A02EB8100211D40 -:10D5D000FFF744FEBDE8F08714000020F4070020A8 -:10D5E0002C00002010B586B000200590049003AAFE -:10D5F00004A905A8FFF7FCFD0022DDE9041013468D -:10D60000CDE9002102901CA11D48039A00F0FEFD07 -:10D610001C4908600846006808B1012400E00024A5 -:10D62000012C15D100BF502080F31188BFF34F8F1C -:10D63000BFF36F8F00BF4FF0FF3013490860012028 -:10D640001249086000201249086000F071F810E0EB -:10D65000601C08B1012000E0002050B900BF50203C -:10D6600080F31188BFF34F8FBFF36F8F00BF00BFF0 -:10D67000FEE706B010BD000049444C450000000024 -:10D68000E9AE0008480000204400002030000020DF -:10D690002800002002480068401C014908607047CB -:10D6A0004C0000201D48006818B101201C4908608A -:10D6B00032E000201A4908601A480068B0FA80F089 -:10D6C000C0F11F0101EB8100174A52F8200008B198 -:10D6D000012000E0002050B900BF502080F31188E5 -:10D6E000BFF34F8FBFF36F8F00BF00BFFEE701EBAB -:10D6F00081020D4B03EB820042685268426000F1E8 -:10D7000008024368934202D142685268426042680C -:10D71000D268064B1A6000BF704700004C00002022 -:10D72000380000202C000020F40700201400002006 -:10D730001CB5524800685249884201D0012000E0DF -:10D74000002050B900BF502080F31188BFF34F8FE5 -:10D75000BFF36F8F00BF00BFFEE74848006848492D -:10D76000491E884201D0012000E0002050B900BFCE -:10D77000502080F31188BFF34F8FBFF36F8F00BF2E -:10D7800000BFFEE73F49084600780190FF200A46A7 -:10D7900010700846007800909DF8000000F0F0003E -:10D7A0009DF80020904201D1012000E0002050B9F6 -:10D7B00000BF502080F31188BFF34F8FBFF36F8FEE -:10D7C00000BF00BFFEE79DF8000000F050002E4AA9 -:10D7D000107007202D4A106009E02C480068401E98 -:10D7E0002A4A10609DF800004006000E00909DF847 -:10D7F000000000F080008028EFD024480068C0F1CD -:10D800000700042801D1012000E0002050B900BF2A -:10D81000502080F31188BFF34F8FBFF36F8F00BF8D -:10D8200000BFFEE7194800680002184A1060104661 -:10D83000008800F4E0601060124A019810700F48F0 -:10D840002030006840F470000C4920310860084620 -:10D85000006840F070400860FFF7A6FD00200C490A -:10D860000860F2F7C1FC0B48006840F040400949ED -:10D870000860F2F7A5FC00201CBD000000ED00E0F0 -:10D8800071C20F4100E400E0740000207800002025 -:10D890007000002034EF00E02DE9F041044601263D -:10D8A000002722460021012000F007F805462846FF -:10D8B000FDF72EFB2846BDE8F0812DE9F84305462B -:10D8C0000E4617460DB1012000E0002050B900BF00 -:10D8D000502080F31188BFF34F8FBFF36F8F00BFCD -:10D8E00000BFFEE705FB06F808F14800FDF78AFCDB -:10D8F000044664B1A14609F14809002084F84600B5 -:10D900003B464A46314628460094FDF710FB204628 -:10D91000BDE8F8832DE9F84380460E4617461D46BC -:10D92000DDF82090B8F1000F01D0012000E00020C8 -:10D9300050B900BF502080F31188BFF34F8FBFF361 -:10D940006F8F00BF00BFFEE70DB1012000E0002097 -:10D9500050B900BF502080F31188BFF34F8FBFF341 -:10D960006F8F00BF00BFFEE707B10EB1012000E0DE -:10D97000002050B900BF502080F31188BFF34F8FB3 -:10D98000BFF36F8F00BF00BFFEE707B90EB90120DC -:10D9900000E0002050B900BF502080F31188BFF391 -:10D9A0004F8FBFF36F8F00BF00BFFEE7482000908E -:10D9B0000098482801D1012000E0002050B900BFA4 -:10D9C000502080F31188BFF34F8FBFF36F8F00BFDC -:10D9D00000BFFEE700BF2C464CB1012084F8460092 -:10D9E0004B463A46314640460094FDF7A0FA2046A1 -:10D9F000BDE8F88370B505460E462C4654B900BF05 -:10DA0000502080F31188BFF34F8FBFF36F8F00BF9B -:10DA100000BFFEE7FFF72EFCD4E90F12206801FBE0 -:10DA20000200A0600020A06320686060E06B401EE0 -:10DA3000226C216800FB0211E160FF2084F84400A1 -:10DA400084F845009EB9206908B9012000E0002053 -:10DA5000A8B904F1100000F0BBFD80B14FF0805078 -:10DA600009490860BFF34F8FBFF36F8F07E004F1E0 -:10DA70001000FFF7C9FB04F12400FFF7C5FBFFF717 -:10DA800023FC012070BD000004ED00E02DE9FF4300 -:10DA900083B0064688461D464FF00009344654B907 -:10DAA00000BF502080F31188BFF34F8FBFF36F8FFB -:10DAB00000BF00BFFEE7B8F1000F01D1206C08B92C -:10DAC000012000E0002050B900BF502080F31188F1 -:10DAD000BFF34F8FBFF36F8F00BF00BFFEE7022D74 -:10DAE00002D1E06B012801D1012000E0002050B9F3 -:10DAF00000BF502080F31188BFF34F8FBFF36F8FAB -:10DB000000BF00BFFEE700F0DFFB08B9059808B9C9 -:10DB1000012000E0002050B900BF502080F31188A0 -:10DB2000BFF34F8FBFF36F8F00BF00BFFEE700BF93 -:10DB3000FFF7A0FBA06BE16B884201D3022D28D137 -:10DB40002A4641462046FDF720F90746606A08B993 -:10DB5000012000E0002068B904F1240000F038FD45 -:10DB600088B14FF0805032490860BFF34F8FBFF348 -:10DB70006F8F08E03FB14FF080502D490860BFF330 -:10DB80004F8FBFF36F8FFFF79FFB012007B0BDE8FA -:10DB9000F083059818B9FFF797FB0020F6E7B9F175 -:10DBA000000F04D101A8FFF77DFC4FF00109FFF73A -:10DBB0008BFBFFF76FFDFFF75DFB94F94400401C02 -:10DBC00010B9002084F8440094F94500401C10B9B5 -:10DBD000002084F84500FFF777FB05A901A800F0B5 -:10DBE0009DFAF0B92046FDF784FAA0B104F11000C7 -:10DBF0000599FFF769FC2046FDF7C4FA00F034FDF3 -:10DC0000002895D14FF0805009490860BFF34F8F2D -:10DC1000BFF36F8F8CE72046FDF7B4FA00F024FDC8 -:10DC200086E72046FDF7AEFA00F01EFD0020ADE7C6 -:10DC300004ED00E02DE9F84F07468A4690461E465F -:10DC40003C4654B900BF502080F31188BFF34F8F7A -:10DC5000BFF36F8F00BF00BFFEE7BAF1000F01D125 -:10DC6000206C08B9012000E0002050B900BF50200E -:10DC700080F31188BFF34F8FBFF36F8F00BF00BFDA -:10DC8000FEE7022E02D1E06B012801D1012000E065 -:10DC9000002050B900BF502080F31188BFF34F8F90 -:10DCA000BFF36F8F00BF00BFFEE7FFF791FB00BF20 -:10DCB0005021EFF3118081F31188BFF34F8FBFF331 -:10DCC0006F8F00BF0546A06BE16B884201D3022E27 -:10DCD00025D194F945B0A06B0090324651462046BC -:10DCE000FDF753F80BF1010088B9606A08B901200B -:10DCF00000E0002050B904F1240000F069FC28B1D4 -:10DD0000B8F1000F02D00120C8F8000004E00BF1C8 -:10DD1000010040B284F845004FF0010901E04FF0E6 -:10DD2000000900BF85F3118800BF4846BDE8F88FA1 -:10DD30002DE9F74183B005460E464FF000082C460A -:10DD400054B900BF502080F31188BFF34F8FBFF349 -:10DD50006F8F00BF00BFFEE70EB9206C08B901202D -:10DD600000E0002050B900BF502080F31188BFF3BD -:10DD70004F8FBFF36F8F00BF00BFFEE700F0A4FA24 -:10DD800008B9059808B9012000E0002050B900BF8B -:10DD9000502080F31188BFF34F8FBFF36F8F00BF08 -:10DDA00000BFFEE700BFFFF765FAA76BF7B131468A -:10DDB0002046FCF7D5FF781EA063206908B9012032 -:10DDC00000E0002060B904F1100000F001FC38B15F -:10DDD0004FF080502F490860BFF34F8FBFF36F8F14 -:10DDE000FFF772FA012006B0BDE8F081059818B976 -:10DDF000FFF76AFA0020F6E7B8F1000F04D101A896 -:10DE0000FFF750FB4FF00108FFF75EFAFFF742FC07 -:10DE1000FFF730FA94F94400401C10B9002084F850 -:10DE2000440094F94500401C10B9002084F84500D6 -:10DE3000FFF74AFA05A901A800F070F9F0B92046E9 -:10DE4000FDF74AF9A0B104F124000599FFF73CFB66 -:10DE50002046FDF797F900F007FC0028A3D14FF00A -:10DE600080500C490860BFF34F8FBFF36F8F9AE764 -:10DE70002046FDF787F900F0F7FB94E72046FDF711 -:10DE800081F900F0F1FB2046FDF726F900288AD041 -:10DE90000020A8E704ED00E02DE9F05F0646894682 -:10DEA0001746344654B900BF502080F31188BFF3A1 -:10DEB0004F8FBFF36F8F00BF00BFFEE7B9F1000FB8 -:10DEC00001D1206C08B9012000E0002050B900BF4A -:10DED000502080F31188BFF34F8FBFF36F8F00BFC7 -:10DEE00000BFFEE7FFF774FA00BF5021EFF3118087 -:10DEF00081F31188BFF34F8FBFF36F8F00BF0546CB -:10DF0000D4F838A0BAF1000F22D094F944B04946B1 -:10DF10002046FCF725FFAAF10100A0630BF10100E8 -:10DF200070B9206908B9012000E0002068B904F147 -:10DF3000100000F04DFB40B13FB10120386004E01B -:10DF40000BF1010040B284F844004FF0010801E0F9 -:10DF50004FF0000800BF85F3118800BF4046BDE8C0 -:10DF6000F09F00002DE9F34182B005464FF0000814 -:10DF70002C46002654B900BF502080F31188BFF30F -:10DF80004F8FBFF36F8F00BF00BFFEE7206C08B953 -:10DF9000012000E0002050B900BF502080F311881C -:10DFA000BFF34F8FBFF36F8F00BF00BFFEE700F0DE -:10DFB0008BF908B9039808B9012000E0002050B996 -:10DFC00000BF502080F31188BFF34F8FBFF36F8FD6 -:10DFD00000BF00BFFEE700BFFFF74CF9A76BFFB122 -:10DFE000781EA063206810B9FDF7B2F9A06020691F -:10DFF00008B9012000E0002060B904F1100000F031 -:10E00000E7FA38B14FF0805043490860BFF34F8FB3 -:10E01000BFF36F8FFFF758F9012004B0BDE8F0811E -:10E02000039898B90EB9012000E0002050B900BF54 -:10E03000502080F31188BFF34F8FBFF36F8F00BF65 -:10E0400000BFFEE7FFF740F90020E6E7B8F1000F58 -:10E0500004D16846FFF726FA4FF00108FFF734F9BC -:10E06000FFF718FBFFF706F994F94400401C10B9BC -:10E07000002084F8440094F94500401C10B90020A9 -:10E0800084F84500FFF720F903A9684600F046F838 -:10E0900040BB2046FDF720F8F0B1206838B9FFF703 -:10E0A000E9F8A06800F038FA0646FFF70DF904F128 -:10E0B00024000399FFF708FA2046FDF763F800F003 -:10E0C000D3FA002888D14FF0805013490860BFF37D -:10E0D0004F8FBFF36F8F7FE72046FDF753F800F0B7 -:10E0E000C3FA79E72046FDF74DF800F0BDFA204667 -:10E0F000FCF7F2FF0028EED05EB1FFF7BBF8204638 -:10E10000FCF7AAFE07463946A068FFF7F9F9FFF7C2 -:10E11000DBF8002081E7000004ED00E070B5054663 -:10E120000C4655B900BF502080F31188BFF34F8FC4 -:10E13000BFF36F8F00BF00BFFEE754B900BF502090 -:10E1400080F31188BFF34F8FBFF36F8F00BF00BF05 -:10E15000FEE7FFF78FF8124802686868131A206814 -:10E16000401C08B9002617E00E4928680968884253 -:10E1700004D06868904201D801260DE020689842DA -:10E1800007D92068C01A20602846FFF78BF90026BF -:10E1900002E0002020600126FFF796F8304670BDAF -:10E1A000280000203C0000202DE9FF4F85B080466C -:10E1B00089461746DDE912ABB800FDF723F806469D -:10E1C00056B15420FDF71EF804460CB1266304E056 -:10E1D0003046FFF797F800E000248CB1002084F867 -:10E1E0005100CDE900ABCDE902403A4649464046F0 -:10E1F000089BFCF7AFFE2046FCF734FD012501E04B -:10E200004FF0FF35284609B0BDE8F08F2DE9F04FFB -:10E2100085B00746884691469A46DDE90EB6109CC1 -:10E220000EB1012000E0002050B900BF502080F363 -:10E230001188BFF34F8FBFF36F8F00BF00BFFEE7A2 -:10E240000CB1012000E0002050B900BF502080F345 -:10E250001188BFF34F8FBFF36F8F00BF00BFFEE782 -:10E26000542003900398542801D1012000E000209D -:10E2700050B900BF502080F31188BFF34F8FBFF318 -:10E280006F8F00BF00BFFEE700BFB4B1AEB125463F -:10E290002C462E63022085F85100002004A9534625 -:10E2A0004A46CDE900B1CDE9025041463846FCF777 -:10E2B00051FE2846FCF7D6FC01E0002004900498AB -:10E2C00005B0BDE8F08F00000549096809B90120D3 -:10E2D00005E00449096809B9022000E00020704700 -:10E2E000300000204C000020014908687047000001 -:10E2F0002800002070B5FFF76BF80025014804687E -:10E30000204670BD280000202DE9F0414FF00008A4 -:10E310004448006800287CD143480068451C4248B6 -:10E32000056015BB41480068006808B9012000E09D -:10E33000002050B900BF502080F31188BFF34F8FE9 -:10E34000BFF36F8F00BF00BFFEE73848076838484B -:10E350000068364908603648076036480068401C47 -:10E3600034490860FCF7D4FE00BF3348006885429A -:10E370003CD300BF2D480068006808B9012000E0C8 -:10E38000002020B14FF0FF302B4908602DE02748D6 -:10E390000068C068C4686668B54202D22648066054 -:10E3A00023E0201DFEF710FFA06A18B104F1180049 -:10E3B000FEF70AFF94F82C10012088401F490968D5 -:10E3C00008431E490860E16A01EB81011C4A02EB27 -:10E3D0008100211DFEF742FF1A49E06A0968C96AF7 -:10E3E0008842C7D34FF00108C4E700BF1548006852 -:10E3F000C06A00EB8000124951F82000012801D9C1 -:10E400004FF001081048006808B14FF0010805E01E -:10E41000FFE70E480068401C0C4908604046BDE814 -:10E42000F08100004C00002028000020180000208F -:10E430001C0000203C000020440000202C00002094 -:10E44000F4070020140000203800002034000020D1 -:10E4500070B505462C460026002D55D02B48006887 -:10E46000844201D1012000E0002050B900BF5020BB -:10E4700080F31188BFF34F8FBFF36F8F00BF00BFD2 -:10E48000FEE7A06C50B900BF502080F31188BFF3A5 -:10E490004F8FBFF36F8F00BF00BFFEE7A06C401E21 -:10E4A000A064616CE06A88422ED0A06C60BB201D25 -:10E4B000FEF78AFE78B9E06A00EB8000144951F853 -:10E4C000200040B994F82C100120884011490968B7 -:10E4D000814310480160606CE062E06AC0F10700AF -:10E4E000A06194F82C10012088400A49096808436B -:10E4F00008490860E16A01EB8101054A02EB8100ED -:10E50000211DFEF7ABFE0126304670BD1400002031 -:10E51000F40700202C00002070B505462C4600268C -:10E52000002D4DD02749E06A0968C96A884240D267 -:10E53000A06900F0004028B922480068C06AC0F114 -:10E540000700A061E16A01EB81011F4A02EB810132 -:10E550006069884201D1012000E0002018B3201D2D -:10E56000FEF732FE40B994F82C100120884017497C -:10E57000096881431548016012480068C06AE0627A -:10E5800094F82C10012088401049096808430F496D -:10E590000860E16A01EB81010B4A02EB8100211D59 -:10E5A000FEF75CFE03E007480068C06AE0620126EF -:10E5B00006E00449606C0968C96A884200D20126F5 -:10E5C000304670BD14000020F40700202C0000200D -:10E5D00070B50646F068C46854B900BF502080F397 -:10E5E0001188BFF34F8FBFF36F8F00BF00BFFEE7EF -:10E5F00004F11800FEF7E8FD15480068A8B9201DD1 -:10E60000FEF7E2FD94F82C100120884011490968BA -:10E61000084310490860E16A01EB81010E4A02EBF0 -:10E620008100211DFEF71AFE04E004F118010B48D9 -:10E63000FEF714FE0A49E06A0968C96A884204D9EB -:10E64000012501200749086000E00025284670BD2B -:10E650004C0000202C000020F4070020A808002017 -:10E66000140000203800002070B500240026364831 -:10E67000006850B900BF502080F31188BFF34F8F5E -:10E68000BFF36F8F00BF00BFFEE7FEF7F3FD2E481C -:10E690000068401E2C4908600846006800284FD1D9 -:10E6A0002A48006800284BD024E02948C068C46884 -:10E6B00004F11800FEF788FD201DFEF785FD94F893 -:10E6C0002C1001208840234909680843214908602B -:10E6D000E16A01EB8101204A02EB8100211DFEF776 -:10E6E000BDFD1E49E06A0968C96A884202D301205B -:10E6F0001B4908601648006808B9012000E00020A6 -:10E700000028D2D00CB1FCF703FD1648056865B1AE -:10E7100000BFFFF7F9FD10B10120114908606D1E1F -:10E72000002DF6D100200F4908600D48006838B16F -:10E73000012630070C490860BFF34F8FBFF36F8F7E -:10E74000FEF7C2FD304670BD4C00002024000020C2 -:10E75000A80800202C000020F4070020140000204E -:10E76000380000203400002004ED00E03C51010896 -:10E770009B5B00080000000000000000800000001B -:10E780000000000000000000000610160006101631 -:10E790000000000000000000010203040607080951 -:10E7A000000000000102030400000000000000005F -:10E7B0000200F000F0000000000000000000000077 -:10E7C0000000000000000000000003000000000046 -:10E7D0000000000000000000000000000000000039 -:10E7E0005F6C697374006C69737420616C6C206376 -:10E7F0006F6D6D616E640000001000000008000085 -:10E800000800000008000000008000000040000038 -:10E810005D580008B959000835590008C559000865 -:10E82000C95800080A0000000200000000000000B3 -:10E83000000000004000FE079200FE079204FE0761 -:10E8400002008A04BA028A01AA041907C2B9200088 -:10E8500000000000000000000000000000000000B8 -:10E8600000000000200020002000200024012402DD -:10E87000220222042104200020003800D0A1200020 -:10E880000000000000000000000000000000000088 -:10E89000000000002000A70722012A012A012F0101 -:10E8A000AA072601220116011301C807B0E02000C3 -:10E8B0000000000000000000000000000000000058 -:10E8C0000000000008012701440104013F01440148 -:10E8D0000E011607E501040104010401BFC6200072 -:10E8E0000000000000000000000000000000000028 -:10E8F0000000000084008400F4078F008400F4030B -:10E900002C0227024401840044013606BCBC2000CE -:10E9100000000000000000000000000000000000F7 -:10E9200000000000000000000000000000000000E7 -:10E9300000000000000000000000000000000000D7 -:10E9400000000000000000000000000000000000C7 -:10E9500000000000000000000000000000000000B7 -:10E9600000000000000000000000000000000000A7 -:10E970000000000000000000000000000000000097 -:10E980000000000000000000000000000000000087 -:10E990000000000000000000000000000000000077 -:10E9A0000000000000000000000000000000000067 -:10E9B0000000000000000000000000000000000057 -:10E9C0000000000000000000000000000000000047 -:10E9D0000000000000000000000000000000000037 -:10E9E0000000000000000000000000000000000027 -:10E9F0000000000000000000000000000000000017 -:10EA00000000000000000000000000000000000006 -:10EA10000000000080000001FC7F44044404FC3F2F -:10EA200044244424FC3F14021422F41A1206122235 -:10EA3000D122303CC2B920000000000000000000DC -:10EA400000000000000000000000000000000000C6 -:10EA500000000000800080008000800080008808A6 -:10EA6000881088208420844082408140800080007B -:10EA7000A0004000D0A12000000000000000000025 -:10EA80000000000000000000000000000000000086 -:10EA900000000000000100011F7D441144114411D9 -:10EAA00044115F7D4411241104119C108710427C95 -:10EAB00020001000B0E02000000000000000000076 -:10EAC0000000000000000000000000000000000046 -:10EAD000000000001008B8080F0908090808BF085E -:10EAE00008091C092C080A78CA0F09080808080830 -:10EAF00008080808BFC62000000000000000000051 -:10EB00000000000000000000000000000000000005 -:10EB100000000000080408040804C87F3F0408043B -:10EB20000804A83F18210C110B12080A0804080A4F -:10EB30008A116460BCBC20000000000000000000DE -:10EB400000000000000000000000000000000000C5 -:10EB500000000000000000000000000000000000B5 -:10EB600000000000000000000000000000000000A5 -:10EB70000000000000000000000000000000000095 -:10EB80000000000000000000000000000000000085 -:10EB90000000000000000000000000000000000075 -:10EBA0000000000000000000000000000000000065 -:10EBB0000000000000000000000000000000000055 -:10EBC0000000000000000000000000000000000045 -:10EBD0000000000000000000000000000000000035 -:10EBE0000000000000000000000000000000000025 -:10EBF0000000000000000000000000000000000015 -:10EC00000000000000000000000000000000000004 -:10EC100000000000000000000000000000000000F4 -:10EC200000000000000000000000000000000000E4 -:10EC300000000000000000000000000000000000D4 -:10EC400000000000000000000000000000000000C4 -:10EC500000000000000000000000000000000000B4 -:10EC600000000000000000000000000000000000A4 -:10EC70000000000000000000000000000000000094 -:10EC80000000000000000000000000000000000084 -:10EC900000000000000000000400000C00F8EE037B -:10ECA000081100081100F8FF01081101081101F80E -:10ECB000F701080801C81001489001C87300481006 -:10ECC00002481402441302C4F003020000000000D2 -:10ECD000C2B9200000000000000000000000000099 -:10ECE0000000000000000000000000000000000024 -:10ECF0000000000000000000000000000000000014 -:10ED00000000000000000000000000000000000003 -:10ED1000040000040000040000040000040040049B -:10ED20000060240020C400208401100403080403B0 -:10ED3000080402040402000400000400000400802F -:10ED40000700000200000000D0A120000000000029 -:10ED500000000000000000000000000000000000B3 -:10ED600000000000000000000000000000000000A3 -:10ED70000000000000000000000000000000000093 -:10ED800000000000000000000400EC040010BC03C0 -:10ED9000104400104400104400104500FC450010D1 -:10EDA000E503904400104400104400D0420030427B -:10EDB000000E410082F80740000030000000000013 -:10EDC000B0E0200000000000000000000000000093 -:10EDD0000000000000000000000000000000000033 -:10EDE0000000000000000000000000000000000023 -:10EDF0000000000000000000000000000000000013 -:10EE00008000C081003C800020880020900020907D -:10EE100000FC8100208000608800B09000308107F5 -:10EE200028F9002487002280002080002080002014 -:10EE30008000208000000000BFC62000000000000D -:10EE400000000000000000000000000000000000C2 -:10EE500000000000000000000000000000000000B2 -:10EE600000000000000000000000000000000000A2 -:10EE700000000000000000101000302000202000E2 -:10EE8000202000FCFF03202000202000202000E0A4 -:10EE9000F8013804012684002088002048002070F2 -:10EEA000002030002048003C860390010200000052 -:10EEB000BCBC2000000000000000000000000000BA -:10EEC0000000000000000000000000000000000042 -:10EED0000000000000000000000000000000000032 -:10EEE0000000000000000000000000000000000022 -:10EEF0000000000000000000000000FCFF03000014 -:10EF000000000000000000000000F8FF0100000009 -:10EF1000000000000000000000000000FEFF0700ED -:10EF20000000000000000000C8FD200000000000FC -:10EF300000000000000000000000000000000000D1 -:10EF400000000000000000000000000000000000C1 -:10EF500000000000000000000000000000000000B1 -:10EF600000000000000000000000000000000000A1 -:10EF7000000000102000FEFF01102000F03F0010F4 -:10EF80002000F03F00102000FFFF03102100FCFFD5 -:10EF900000030103FEFF010000000000000000006C -:10EFA000BBF920000000000000000000000000008D -:10EFB0000000000000000000000000000000000051 -:10EFC0000000000000000000000000000000000041 -:10EFD0000000000000000000000000000000000031 -:10EFE0000000000000000000000000400000F01FD2 -:10EFF00000181800040C00FFFF00048200048200C7 -:10F00000FCFF00048000040000040002F8FF01007F -:10F010000000000000000000C9AB2000000000005C -:10F0200000000000000000000000000000000000E0 -:10F0300000000000000000000000000000000000D0 -:10F0400000000000000000000000000000000000C0 -:10F0500000000000000000000000000000000000B0 -:10F0600000000000000000000000000000000000A0 -:10F070000000000000000000000000000000000090 -:10F080000000000000000000000000000000000080 -:10F090000000000000000000000000000000000070 -:10F0A0000000000000000000000000000000000060 -:10F0B0000000000000000000000000000000000050 -:10F0C0000000000000000000000000000000000040 -:10F0D0000000000000000000000000000000000030 -:10F0E0000000000000000000000000000000000020 -:10F0F0000000000000000000000000000000000010 -:10F1000000000000000000000000000000000000FF -:10F1100000000000000000000000000000000000EF -:10F1200000000000000000000000000000000000DF -:10F1300000000000000000000000000000000000CF -:10F1400000000000000000001000003010F0FF3F41 -:10F15000104200104200104200F0FF1F1042081041 -:10F160004208104208F0FF0F10200890C0009041A4 -:10F170000890410E904F0398C100884110884910B3 -:10F1800084473084C13F020000000000C2B9200063 -:10F19000000000000000000000000000000000006F -:10F1A000000000000000000000000000000000005F -:10F1B000000000000000000000000000000000004F -:10F1C000000000000000000000000000000000003F -:10F1D00000000000000000000000001800001800FF -:10F1E000001000001000001000001000809000804F -:10F1F0001101C0100240100460101C3010181010D3 -:10F200003008103004102000100000100000100022 -:10F21000001900001E00000C00000000D0A120001A -:10F2200000000000000000000000000000000000DE -:10F2300000000000000000000000000000000000CE -:10F2400000000000000000000000000000000000BE -:10F2500000000000000000000000000000000000AE -:10F2600000000000000000001000003000FED13F50 -:10F27000201002201002201002201002201402FC94 -:10F28000150220140220D63F201202201202201064 -:10F2900002A009026008021C080206040200020221 -:10F2A00000F13FC00000200000000000B0E020009E -:10F2B000000000000000000000000000000000004E -:10F2C000000000000000000000000000000000003E -:10F2D000000000000000000000000000000000002E -:10F2E000000000000000000000000000000000001E -:10F2F0000000000000000000000400070CF80004FB -:10F30000C00004C06004C0C004C00004FE0704C004 -:10F310000004C02004E06004E04304F04624D0442C -:10F3200074C8800FC87804C40404C20004C0000478 -:10F33000C00004C00004C00004400004BFC6200098 -:10F3400000000000000000000000000000000000BD -:10F3500000000000000000000000000000000000AD -:10F36000000000000000000000000000000000009D -:10F37000000000000000000000000000000000008D -:10F38000000000000000002080006080016080001C -:10F39000608000608000FEFF3F6080006080006051 -:10F3A0008000608200E0FD1F7010086E100C642069 -:10F3B00004602006604002604003608001604003FA -:10F3C00064300E780C7C200310000000BCBC2000D0 -:10F3D000000000000000000000000000000000002D -:10F3E000000000000000000000000000000000001D -:10F3F000000000000000000000000000000000000D -:10F4000000000000000000000000000000000000FC -:10F4100000000000000000000000000000000000EC -:10F420000000C0F8FFC018C0CC18C0CCF8FFCC1842 -:10F43000C0CC180CCC180CCCD8FFCCD8CCCCD8CCA9 -:10F44000CCD8CCCCCCCCC0CCCCC004FCC0060C7E80 -:10F45000000000000000000000000000CBA220001F -:10F46000000000000000000000000000000000009C -:10F47000000000000000000000000000000000008C -:10F48000000000000000000000000000000000007C -:10F49000000000000000000000000000000000006C -:10F4A000000000000000000000000000000000005C -:10F4B000000000F8FF7F180060180060F8FF7F1858 -:10F4C0000666180C06180803D8FF7F180C06180CDF -:10F4D00006F8FFFF0C0C060C0C06040606060306D5 -:10F4E000030106000000000000000000C6C120006B -:10F4F000000000000000000000000000000000000C -:10F5000000000000000000000000000000000000FB -:10F5100000000000000000000000000000000000EB -:10F5200000000000000000000000000000000000DB -:10F5300000000000000000000000000000000000CB -:10F540000200C084FFCC9CC1CC88C1CC80D9CC83C4 -:10F55000D9CC8ED9CC98D9CC80D9CC80D9CC88D9EB -:10F56000CC98CDCC0C0CCC0C36C00C63C0C6C1C042 -:10F5700074807D000000000000000000B2E2200066 -:10F58000000000000000000000000000000000007B -:10F59000000000000000000000000000000000006B -:10F5A000000000000000000000000000000000005B -:10F5B000000000000000000000000000000000004B -:10F5C000000000000000000000000000000000003B -:10F5D00002001B0C007318004338000380FFFF007B -:10F5E00000031F000318000398FF031818021818DF -:10F5F00006981806D8188678188C38F88D9C0F98BD -:10F600000800F0000000000000000000CAD4200044 -:10F6100000000000000000000000000000000000EA -:10F6200000000000000000000000000000000000DA -:10F6300000000000000000000000000000000000CA -:10F6400000000000000000000000000000000000BA -:10F6500000000000000000000000000000000000AA -:10F66000008301FEFFFF008301F0FF3F300030F018 -:10F67000FF3F300030F0FF3F300C30000600FEFF4F -:10F68000FFC0300CF8FF7F67309860301860301F83 -:10F69000003000000000000000000000C4BB20009B -:10F6A000000000000000000000000000000000005A -:10F6B000000000000000000000000000000000004A -:10F6C000000000000000000000000000000000003A -:10F6D000000000000000000000000000000000002A -:10F6E000000000000000000000000000000000001A -:10F6F00000630080C100C080016000033000061874 -:10F70000001C0E00700200C0F8FF0F00030E000383 -:10F710000E800106800106C0000660000738FC0369 -:10F720000E0000000000000000000000B7D620001E -:10F7300000000000000000000000000000000000C9 -:10F7400000000000000000000000000000000000B9 -:10F7500000000000000000000000000000000000A9 -:10F760000000000000000000000000000000000099 -:10F770000000000000000000000000000018600C05 -:10F78000306018306010FEE1FF00600082EDC1C4FF -:10F790006C636C6C36FE65FF30661830661830603E -:10F7A00018FEB1FF3030183818181C1C180E0E182F -:10F7B000020218000000000000000000B1E6200076 -:10F7C0000000000000000000000000000000000039 -:10F7D0000000000000000000000000000000000029 -:10F7E0000000000000000000000000000000000019 -:10F7F0000000000000000000000000000000000009 -:10F8000000000000000000000000000000000000F8 -:10F81000003800007000FFFFFF003800064E608CCB -:10F820006338D03F08001C00202604F8C31CCFFF1B -:10F83000F1023041003000FFFFFF003000003000D7 -:10F84000003000000000000000000000C2CA2000DC -:10F8500000000000000000000000000000000000A8 -:10F860000000000000000000000000000000000098 -:10F870000000000000000000000000000000000088 -:10F880000000000000000000000000000000000078 -:10F8900000000000000000000000000000308000B8 -:10F8A00030800130000330FEFFFE06C03086C430D9 -:10F8B0004018303030301860F00FC03EF87F300014 -:10F8C0000330000330000330000330000330FFFF3B -:10F8D0001E0000000000000000000000BFD8200053 -:10F8E0000000000000000000000000000000000018 -:10F8F0000000000000000000000000000000000008 -:10F9000000000000000000000000000000000000F7 -:10F9100000000000000000000000000000000000E7 -:10F9200000000000000000000000000000000000D7 -:10F930008001609801608C0163FC3F6386016382F3 -:10F940000163FFFF63800163800163FC7F638C615F -:10F95000638C61638C61608C61608C3D6080013F71 -:10F96000000000000000000000000000D6C62000DB -:10F970000000000000000000000000000000000087 -:10F980000000000000000000000000000000000077 -:10F990000000000000000000000000000000000067 -:10F9A0000000000000000000000000000000000057 -:10F9B0000000000000000000000000000000000047 -:10F9C000000000FCC77F0CC6600CC660FCC77F0C43 -:10F9D000C660003006FEFFFF006E0000C701F001A8 -:10F9E0000F1F00F8FCC77F0CC6600CC660FCC77F09 -:10F9F0000CC660000000000000000000C6F72000F8 -:10FA000000000000000000000000000000000000F6 -:10FA100000000000000000000000000000000000E6 -:10FA200000000000000000000000000000000000D6 -:10FA300000000000000000000000000000000000C6 -:10FA400000000000000000000000000000000800AE -:10FA5000001800003000FEFFFF0600C00600C0E0F6 -:10FA6000FF0F00000700800100E000003000FFFFF2 -:10FA7000FF003000003000003000003000801F0028 -:10FA8000000000000000000000000000D7D62000A9 -:10FA90000000000000000000000000000000000066 -:10FAA0000000000000000000000000000000000056 -:10FAB0000000000000000000000000000000000046 -:10FAC0000000000000000000000000000000000036 -:10FAD0000000000000000000000000000020800185 -:10FAE00030C000F8DFFFC8600684710C02390801DD -:10FAF000100060000C70000CB8FFFF3C000C3604D6 -:10FB00000C320C0C30180C30100C30000C30000C87 -:10FB100030E007000000000000000000B7FB2000FC -:10FB200000000000000000000000000000000000D5 -:10FB300000000000000000000000000000000000C5 -:10FB400000000000000000000000000000000000B5 -:10FB500000000000000000000000000000000000A5 -:10FB60000000000000000000000000000000000095 -:10FB7000C0300060E000F0FFFF386000F6FFFF33A8 -:10FB80006000F0FFFF306000F0FFFF300000003049 -:10FB900000003000FEFFFF00FE01803107703038AA -:10FBA0000F30C0000000000000000000BCAF2000CB -:10FBB0000000000000000000000000000000000045 -:10FBC0000000000000000000000000000000000035 -:10FBD0000000000000000000000000000000000025 -:10FBE0000000000000000000000000000000000015 -:10FBF0000000000000000000000000000000000005 -:10FC0000001800001800001800001800FCFF7F0C0E -:10FC100018600C18600C18600C18600C1860FCFF61 -:10FC20007F0C186000180000180000180000180071 -:10FC3000001800000000000000000000D6D02000E6 -:10FC400000000000000000000000000000000000B4 -:10FC500000000000000000000000000000000000A4 -:10FC60000000000000000000000000000000000094 -:10FC70000000000000000000000000000000000084 -:10FC800000000000000000000000000000001C0058 -:10FC9000003800006000FFFFFF60000C60000CC037 -:10FCA0000006C0000680010300830100C700006C4D -:10FCB0000000380000EE00C0830778003C0600E03A -:10FCC000000000000000000000000000CEC4200082 -:10FCD0000000000000000000000000000000000024 -:10FCE0000000000000000000000000000000000014 -:10FCF0000000000000000000000000000000000004 -:10FD000000000000000000000000000000000000F3 -:10FD100000000000000000000000000000000000E3 -:10FD2000000000F8FF3F180030180030F8FF3F18BF -:10FD30000030180030F8FF3F18003004C62008C615 -:10FD40003018C63830C61820C60800C600FEFFFFAF -:10FD5000000000000000000000000000CFD42000E0 -:10FD60000000000000000000000000000000000093 -:10FD70000000000000000000000000000000000083 -:10FD80000000000000000000000000000000000073 -:10FD90000000000000000000000000000000000063 -:10FDA0000000000000000000000000000000000053 -:10FDB000000000FCFF7F00000000000000000000C9 -:10FDC0000000FFFFFF00300020300430300C3830DE -:10FDD000181830300C30600630C00230800030001F -:10FDE000801F00000000000000000000CABE2000CC -:10FDF0000000000000000000000000000000000003 -:10FE000000000000000000000000000000000000F2 -:10FE100000000000000000000000000000000000E2 -:10FE200000000000000000000000000000000000D2 -:10FE300000000000000000000000000000000000C2 -:10FE4000000000FEFFFF00300000300000300030F6 -:10FE5000300030300030300030F07F303000303053 -:10FE600000303000303000303000303000FFFFFF15 -:10FE7000000000000000000000000000D5FD200090 -:10FE80000000000000000000000000000000000072 -:10FE90000000000000000000000000000000000062 -:10FEA0000000000000000000000000000000000052 -:10FEB0000000000000000000000000000000000042 -:10FEC0000000000000000000000000000000000032 -:10FED000000300800100C0FF076000033880010CB0 -:10FEE0006000F4FF3F3000303030303030303030A0 -:10FEF0003030303030303030F83000980300070EAA -:10FF0000E001781E00C0000000000000B8BA200028 -:10FF100000000000000000000000000000000000E1 -:10FF200000000000000000000000000000000000D1 -:10FF300000000000000000000000000000000000C1 -:10FF400000000000000000000000000000000000B1 -:10FF500000000000000000000000000000000000A1 -:10FF6000003000003000003000003000603006300B -:10FF7000300C30301C1830381830300C30600E30F7 -:10FF8000E00630C0023080003000003000C01F00AA -:10FF9000000000000000000000000000D0A12000D0 -:10FFA0000000000000000000000000000000000051 -:10FFB0000000000000000000000000000000000041 -:10FFC0000000000000000000000000000000000031 -:10FFD0000000000000000000000000000000000021 -:10FFE0000000000000000000000000000000000011 -:10FFF000C00003C60C01C48601C080FFFECF60E0D4 +:1002E0004346BDE8F09F2DE9F0410024061B25465A +:1002F00071F1000605DA01240027D0EB070067EB57 +:100300000101161E73F1000605DA0027D2EB070281 +:10031000012567EB0303FFF7B5FF86460E46174638 +:100320009C46AC4204D00025D0EB050E65EB0106DF +:1003300024B10020D2EB000760EB030C704631467D +:100340003A466346BDE8F08110B5431A934209D29C +:100350008318881803E010F8011D03F8011D521ED0 +:10036000F9D210BD40EA01039B0703D009E008C998 +:10037000121F08C0042AFAD203E011F8013B00F86A +:10038000013B521EF9D210BDD2B201E000F8012BA0 +:10039000491EFBD270470022F6E710B513460A4605 +:1003A00004461946FFF7F0FF204610BD421C10F826 +:1003B000011B0029FBD1801A704710B5002200E014 +:1003C000521C835C8C5CA34201D1002BF8D1D8B2C3 +:1003D000E1B2401A10BD034611F8012B00F8012BC1 +:1003E000002AF9D11846704730B50546002003466B +:1003F00000E05B1C934205D2EC5CC85C201A01D182 +:10040000002CF6D130BD2DE9FE4F804681EA030075 +:10041000C00F0C46009021F0004123F00045B8EBDE +:100420000200A94105D24046214690461C460B4693 +:10043000024623F00040104347D0270DC7F30A00BF +:10044000C3F30A510290401A019040286BDAC3F3BB +:10045000130040F4801B0098924620B10023D2EB99 +:10046000030A63EB0B0B01985946C0F1400250465A +:1004700000F040F906460D4650465946019A00F0F4 +:1004800058F910EB08006141002487EA115284EA10 +:10049000E7731A4340D0009A62B3019A012A4FEAE7 +:1004A000075215DC001B61EB02014FF0004202EA2B +:1004B0000752CDE90042001C41F5801132462B461F +:1004C00000F058F903B0BDE8F08F40462146F9E747 +:1004D000001B61EB0201001C41F5801300185B4119 +:1004E0002018A2F5001747EB030140EAD570B619B2 +:1004F0006D4111E06D084FEA360645EAC0754FEAD6 +:100500000752001B61EB0201001C41F580114908F4 +:100510004FEA30000019514132462B4603B0BDE886 +:10052000F04F00F018B90098012240000023D0EBF2 +:10053000020263EBE073009821464FEAE074B8EBE7 +:10054000000061EB0401E9E783F000435BE781F021 +:10055000004158E72DE9FE4F81EA030404F000440E +:1005600021F0004100944FF0000B23F0004350EACB +:1005700001045ED052EA03045BD0C3F30A54C1F312 +:100580000A552C44A4F2F3340194A0FB0254C1F3A5 +:10059000130141F48011C3F3130343F4801301FBEF +:1005A000024400FB034E840A970A44EA815447EA56 +:1005B0008357A4FB076802958D0A05FB07854FEA60 +:1005C000932C04FB0C542705029D4FEA065847EA7A +:1005D0001637B5EB08056EEB070C870E920E47EA4F +:1005E000811742EA8312A7FB0201B6EB0B0164EB11 +:1005F00000042B0D43EA0C335E1844EB1C50DA4622 +:100600005146E7FB0201C5F313044FEA0B3343EAFB +:1006100014534FEA0432019C43EA0603A4F10C048C +:100620000294009CCDE900B400F0A4F803B0BDE84A +:10063000F08F00200146F9E70EB5C10F80EAE070A7 +:100640000844CA07002140F233438DE80E000A46F1 +:100650000B4600F08FF803B000BD70B5C1F30A522D +:1006600001F000450024C1F3130140F2FF3341F4CF +:1006700080119A4201DA002070BD40F233439A4261 +:10068000A2F2334203DC524200F043F800E0904013 +:100690002C43F1D0404270BD30B5041E71F100040E +:1006A00004DB4FF00044404264EB0101141E73F17F +:1006B000000405DB1C464FF00043524263EB040389 +:1006C0008B4208BF824230BD30B50B460146002048 +:1006D0002022012409E021FA02F59D4205D303FA04 +:1006E00002F5491B04FA02F52844151EA2F1010285 +:1006F000F1DC30BD202A04DB203A00FA02F10020B0 +:1007000070479140C2F1200320FA03F3194390404F +:100710007047202A04DB203A21FA02F000217047BA +:1007200021FA02F3D040C2F1200291400843194659 +:100730007047202A06DBCB17203A41FA02F043EA41 +:10074000E07306E041FA02F3D040C2F1200291408A +:1007500008431946704710B5141E73F1000408DAF7 +:10076000401C41F1000192185B411A4301D120F075 +:10077000010010BD2DE9F04D92469B4611B1B1FA32 +:1007800081F202E0B0FA80F220329046FFF7B2FF29 +:1007900004460F4640EA0A0041EA0B0153465A4616 +:1007A000084313D0114653EA010019D0C8F14002A2 +:1007B0005046FFF7AEFF05460E46504659464246A4 +:1007C000FFF798FF084305D0012004E02046394692 +:1007D000BDE8F08D0020054346EAE0762C43374320 +:1007E0000A986305E40AA0EB08000022FD0A44EA27 +:1007F00047540A3002D500200146E9E701051019E7 +:100800006941DDE9084500196941BDE8F04DA2E7FD +:100810002DE9F04D81EA030404F0004B21F000457E +:1008200014464FF0000A23F0004150EA050220D0A0 +:1008300054EA01021DD0C5F30A570246C5F313035B +:10084000C1F31300C1F30A5640F4801543F480133A +:10085000A7EB0608101BD64608F2FD3873EB05001F +:1008600002D308F1010801E092185B41B8F1000FD2 +:1008700003DA00200146BDE8F08D00204FF480111E +:10088000064684460EE0171B73EB050705D3121BC3 +:1008900063EB050306434CEA010C49084FEA3000BC +:1008A00092185B4150EA0107EDD152EA030012D0E1 +:1008B00082EA040083EA0501084305D0101BAB411E +:1008C00006D20122002306E000224FF0004302E09E +:1008D0006FF0010253101AEB06004CEB085110EBBD +:1008E0000A0041EB0B01BDE8F04DFFF734BFC1F347 +:1008F0000A52C1F3130140F2FF3341F480119A42CE +:1009000002DA00200146704740F233439A42A2F2D5 +:10091000334202DC5242FFF7FCBEFFF7EBBE0000A1 +:1009200030B5041E71F1000404DB4FF00044404276 +:1009300064EB0101141E73F1000405DB1C464FF04B +:100940000043524263EB0403994208BF904230BD1A +:10095000064C074D06E0E06840F0010394E807000C +:1009600098471034AC42F6D3FFF712FC3C61010803 +:100970006C61010870B58C1810F8015B15F0070365 +:1009800001D110F8013B2A1106D110F8012B03E028 +:1009900010F8016B01F8016B5B1EF9D12B0705D430 +:1009A0000023521E0DD401F8013BFAE710F8013B79 +:1009B000CB1A921C03E013F8015B01F8015B521E95 +:1009C000F9D5A142D8D3002070BD000010B5012494 +:1009D000A102034800F03AFD00B10024204610BDFA +:1009E0000004024010B504462146024802F0DCFC37 +:1009F00010BD0000C804002010B5044802F0E7FC58 +:100A0000042801D0012010BD0020FCE7C80400200C +:100A100010B5002400F014F8012801D0012010BD09 +:100A2000064802F0E6FC044634B94FF4006103487E +:100A300002F070FB00B101242046F0E7C80400205A +:100A400008B501200090FFF7C1FF08B90020009011 +:100A50009DF8000008BD00002DE9F04104460D4658 +:100A60001646002733462A462146044802F0F6FD82 +:100A700000B101273846BDE8F0810000C80400201D +:100A800010B500220121024800680AF07DFA10BD6D +:100A9000D80000202DE9F04104460D4616460027F7 +:100AA00033462A462146044802F086FE00B101275B +:100AB0003846BDE8F0810000C804002000BFFEE712 +:100AC0000346042B15D007DC7BB1012B0ED0022B83 +:100AD0000DD0032B12D10BE0202B0BD0212B0AD0F1 +:100AE000222B09D0232B09D107E008E007E006E01C +:100AF00005E004E003E002E001E000E000BF00BF29 +:100B0000002070470020704710B5002204490548B6 +:100B100005F0F9FF0449034805F0E6FF002010BD89 +:100B20000C150120300801200C0D012070B5044681 +:100B30000D462046296810F009FE2146034805F0BD +:100B4000D3FF024805F09CFF002070BD3008012053 +:100B500010B503460C460021084610BD2DE9F041B2 +:100B600004460D4600260A48D0F8BC72D7F8140295 +:100B700010B10120BDE8F0812A462146044805F065 +:100B8000C2FF034806F072F806463046F2E700005E +:100B900030080120024600BF1AB901E000BF00BFC3 +:100BA000FCE700BF0120704710B5024800F060F973 +:100BB00010BD0000A806002010B5024800F058F94A +:100BC00010BD00004C05002010B5024800F050F99F +:100BD00010BD0000AC05002010B5024800F048F937 +:100BE00010BD0000080700200146087810381823BF +:100BF000B0FBF3F20848805CC865032A05D9086891 +:100C00006FF30900001D886503E008686FF30900B1 +:100C10008865886D704700005C2E01080146002041 +:100C20008A6A8B69CBB932B1012A0DD0022A03D06E +:100C3000032A10D10EE000BFCB6A03F08073B3F13A +:100C4000807F00D1012007E0CB6AB3F1C07F00D1E3 +:100C5000012001E000E000BF34E08B69B3F5005FE4 +:100C60001AD132B1012A07D0022A03D0032A11D1A6 +:100C70000AE000BF01200EE0CB6A03F08073B3F1FD +:100C8000807F00D1012006E0CB6AB3F1C07F00D1A4 +:100C9000012000E000BF15E032B1012A05D0022A90 +:100CA00004D0032A0CD103E000BF00BF012008E0FC +:100CB000CB6A03F08073B3F1807F00D1012000E0A4 +:100CC00000BF00BF704730B50468246824F4802456 +:100CD00005682C60046863608468402C04D1046853 +:100CE000A2600468E16003E00468A1600468E26057 +:100CF00030BD704772B600BFFEE730B504460D4602 +:100D000000222946204600F001F830BDF0B5034628 +:100D1000012500241148807B02281CDA00200F4E98 +:100D2000B67B0E4FB8553846867B001D40F82630FE +:100D3000001F867B0C3082553E46B07B461CBE733E +:100D4000044604F1300008703A2048702F20887063 +:100D50000020C87000252846F0BD000020080120B2 +:100D600070B50A480468001D0568001D0668344413 +:100D700054B108220649204603F0B5FB0422044979 +:100D80001031284603F0AFFB70BD0000107AFF1F42 +:100D90001A01002070B50446A56D00F06FFB0646F1 +:100DA00094F83500022808D08020606500BF00203C +:100DB00084F8340000BF012070BD2068006820F076 +:100DC0001600216808602068406920F080002168D2 +:100DD0004861206C08B9A06C28B12068006820F038 +:100DE0000800216808602068006820F00100216880 +:100DF000086010E000F042FB801B05280BD9202082 +:100E00006065032084F8350000BF002084F83400BA +:100E100000BF0320D0E72068006800F00100002830 +:100E2000E8D194F85C103F208840A860012084F845 +:100E3000350000BF002084F8340000BF00BFBBE7CE +:100E4000014691F83500022803D080204865012032 +:100E50007047052081F835000868006820F001001F +:100E60000A6810600020F3E70146486D70470000F3 +:100E7000F8B50446002000908C4800684FF41651E5 +:100E8000B0FBF1F7A56D2E6894F85C10082088403F +:100E9000304098B12068006800F0040070B120680C +:100EA000006820F004002168086094F85C100820B5 +:100EB0008840A860606D40F00100606594F85C10A7 +:100EC00001208840304068B12068406900F080000F +:100ED00040B194F85C1001208840A860606D40F03B +:100EE0000200606594F85C1004208840304068B1CE +:100EF0002068006800F0020040B194F85C10042003 +:100F00008840A860606D40F00400606594F85C1053 +:100F100010208840304078B32068006800F0080056 +:100F200050B394F85C1010208840A86020680068D6 +:100F300000F4802080B12068006800F4002028B907 +:100F4000206CC8B12046216C884715E0A06C98B190 +:100F50002046A16C88470FE02068006800F480708C +:100F600028B92068006820F0080021680860206C1B +:100F700010B12046216C884794F85C1020208840EE +:100F80003040002865D02068006800F0100000287C +:100F90005FD094F85C1020208840A86094F8350059 +:100FA000052828D12068006820F016002168086014 +:100FB0002068406920F0800021684861206C08B9F1 +:100FC000A06C28B12068006820F008002168086043 +:100FD00094F85C103F208840A860012084F8350018 +:100FE00000BF002084F8340000BF206D10B12046FF +:100FF000216D8847F8BD2068006800F4802080B12A +:101000002068006800F4002028B9606C10B1204608 +:10101000616C88471DE0E06BD8B12046E16B8847E2 +:1010200017E02068006800F4807068B920680068E4 +:1010300020F0100021680860012084F8350000BF0E +:10104000002084F8340000BFE06B10B12046E16B53 +:101050008847606D38B3606D00F00100F0B1052085 +:1010600084F835002068006820F0010021680860DD +:1010700000BF0098401C0090B84200D905E02068ED +:10108000006800F001000028F3D100BF012084F8BF +:10109000350000BF002084F8340000BFE06C10B1C0 +:1010A0002046E16C884700BFA4E700001000002044 +:1010B0002DE9F0410446002500F0E0F9074614B997 +:1010C0000120BDE8F081606A00B100BF022084F811 +:1010D000350000BF002084F8340000BF206800689D +:1010E00020F00100216808600AE000F0C7F9C01B89 +:1010F000052805D920206065032084F83500E0E745 +:101100002068006800F001000028EED12068056822 +:1011100021480540D4E901010843E16808432169F9 +:10112000084361690843A1690843E1690843216AEA +:1011300008430543606A042803D1D4E90B0108433E +:101140000543206805602068456925F00705606A49 +:101150000543606A04280DD1A06A0543E06A48B1DE +:101160002046FFF75BFD28B140206065012084F830 +:101170003500A6E7206845612046FFF735FD0646A5 +:1011800094F85C103F208840B0600020606501202A +:1011900084F83500002094E73F8010F02DE9F047F7 +:1011A00004460D4616461F464FF00008D4F85890E6 +:1011B00000BF94F83400012802D10220BDE8F08776 +:1011C000012084F8340000BF94F83500012825D1AF +:1011D000022084F83500002060653B4632462946EF +:1011E0002046FFF770FD94F85C103F208840C9F856 +:1011F00008002068006840F0160021680860206C34 +:1012000028B12068006840F0080021680860206864 +:10121000006840F001002168086006E000BF00207F +:1012200084F8340000BF4FF002084046C6E70000D3 +:1012300070B5044600F022F906462546681C10B138 +:1012400004480078054400BF00F018F9801BA8424C +:10125000FAD370BD0C000020F8B502460B460025FD +:10126000002400200021D6E0012606FA01F51E68C0 +:1012700006EA0504AC4274D11E7906F00306012E7D +:1012800004D01E7906F00306022E13D190684F0099 +:101290000326BE40B0434F00DE68BE40304390603E +:1012A000506801268E40B0431E79C6F300168E406A +:1012B000304350601E7906F00306032E09D0D06833 +:1012C0004F000326BE40B0434F009E68BE403043EF +:1012D000D0601E7906F00306022E13D1CF0802F16A +:1012E000200656F827004E07F70E0F26BE40B043E3 +:1012F0004F07FF0E1E69BE403043CF0802F12006A3 +:1013000046F8270010684F000326BE40B0431E7900 +:1013100006F003064F00BE40304310605E6806F4DE +:101320004036002E76D000BF002600963C4E366830 +:1013300046F480463A4F3E603E46366806F48046A4 +:10134000009600BF00BF374E8F0856F827008E0763 +:10135000370F0F26BE40B043334EB24202D10026B3 +:1013600024E057E0314EB24201D101261EE0304E5A +:10137000B24201D1022619E02E4EB24201D103261B +:1013800014E02D4EB24201D104260FE02B4EB242A2 +:1013900001D105260AE02A4EB24201D1062605E017 +:1013A000284EB24201D1072600E008268F073F0FE2 +:1013B000BE4030431B4E8F0846F82700224E30684F +:1013C000A0435E6806F4801606B120431E4E3060CE +:1013D000361D3068A0435E6806F4001606B120434F +:1013E000194E361D3060184E361F3068A0435E68B7 +:1013F00006F4003606B12043134E361F3060361F08 +:101400003068A0435E6806F4803606B120430E4E75 +:10141000083E3060491C1029FFF426AFF8BD0000DB +:1014200044380240083801400000024000040240F5 +:1014300000080240000C024000100240001402406C +:1014400000180240001C0240083C0140024613699B +:101450000B400BB1012000E00020704710B542693D +:1014600021EA020302EA010443EA0443836110BD56 +:101470000AB1816101E00B04836170470148006893 +:101480007047000004000020034800680349097801 +:101490000844014908607047040000200C00002047 +:1014A00010B50D48006840F400700B49086008460C +:1014B000006840F4806008600846006840F480706E +:1014C0000860032000F0DCF8042000F007F800F0CA +:1014D0005FF8002010BD0000003C02402DE9F04103 +:1014E00088B004460027B84600BF0020019023487A +:1014F000006840F01000214908600846006800F0CC +:101500001000019000BF00BF02A903A801F052F92A +:10151000069F1FB901F076F9054602E001F072F965 +:1015200045001748B5FBF0F0A0F101081548164931 +:10153000086040F2E7311448C160C0F8048000211F +:1015400001618160816102F0A0FB064696B90E48F8 +:1015500002F0D0FB06466EB9362000F043F8102C9E +:1015600007D200222146362000F04CF807480460DC +:1015700000E00126304608B0BDE8F0814038024066 +:1015800040420F00001000406807002008000020C3 +:1015900008B500BF002000901148006840F480406A +:1015A0000F4908600846006800F48040009000BFC2 +:1015B00000BF00BF00200090081F006840F080506E +:1015C000091F08600846006800F08050009000BFC6 +:1015D00000BF00220F21901E00F014F808BD00008B +:1015E0004438024001460846002809DB00F01F038A +:1015F00001229A4043099B0003F1E023C3F8002134 +:1016000000BF70472DE9F05F80460D461646002763 +:1016100007F000FD074639462A46334601F0070029 +:10162000C0F1070ABAF1040F02D94FF0040A01E031 +:10163000C0F1070AD14600F1040ABAF1070F02D23D +:101640004FF0000A01E0A0F1030AD4464FF0010A6E +:101650000AFA09FAAAF1010A0AEA020A0AFA0CFAD3 +:101660004FF0010B0BFA0CFBABF1010B0BEA030B78 +:101670004AEA0B042146404607F0D4FCBDE8F09F3F +:1016800000BF00F00702064B19684FF6FF03194030 +:10169000044B0B4343EA0221014B196000BF704722 +:1016A0000CED00E00000FA05704702461068416248 +:1016B00000207047F0B5034615461868446A21B902 +:1016C00044EA05401E68B06219E01868806A04EBBD +:1016D0001044002208E0186800F5827050F82200DB +:1016E00004EB1044501CC2B2481E9042F3D844EAA6 +:1016F0000547186800F582704E1E40F826700020DD +:10170000F0BD10B50446D4F8080505F01AFF10BD69 +:1017100070B504460D4605EBC50304F13C0101EB31 +:1017200083010A692946D4F8080505F005FE70BD55 +:1017300070B504460D4605EBC50304F51F7101EBBA +:1017400083010A692946D4F8080505F079FE70BDC1 +:1017500010B50446D4F8080505F0F6FE10BD2DE9D5 +:10176000F04104460D4605F08000802808D105F0C0 +:101770000F0000EBC00104F13C0000EB810607E024 +:1017800005F00F0000EBC00104F51F7000EB8106AF +:101790003146206807F0CAF907463846BDE8F081AF +:1017A00070B504460E4606F0800080280AD106F087 +:1017B0000F0000EBC00104F13C0000EB81050120AB +:1017C000687009E006F00F0000EBC00104F51F701F +:1017D00000EB81050020687006F00F00287000BF44 +:1017E00094F8BC04012801D1022070BD012084F8C6 +:1017F000BC0400BF2946206806F078FC00BF00202A +:1018000084F8BC0400BF00BFEFE770B504460E4685 +:1018100006F00F006168884201D9012070BD06F012 +:10182000800080280AD106F00F0000EBC00104F10F +:101830003C0000EB81050120687009E006F00F0014 +:1018400000EBC00104F51F7000EB810500206870FB +:101850000020A87006F00F00287000BF94F8BC04A8 +:10186000012801D10220D9E7012084F8BC0400BF7F +:101870002946206806F022FF00BF002084F8BC043F +:1018800000BF00BFCAE7024601F00F0000EBC00333 +:1018900002F51F7000EB8300006A70472DE9F047E6 +:1018A00005460E4690461F464FF0000906F08000A0 +:1018B00080280AD106F00F0000EBC00105F13C00C2 +:1018C00000EB81040120607009E006F00F0000EBDE +:1018D000C00105F51F7000EB81040020607006F068 +:1018E0000F002070C4F80C802771607808B1207850 +:1018F0002081022F01D10020607100BF95F8BC0447 +:10190000012802D10220BDE8F087012085F8BC043F +:1019100000BF2146286806F0FFFA00BF002085F8C6 +:10192000BC0400BF4846EEE72DE9F04104460E46F0 +:101930001746984606F00F0000EBC00104F51F7033 +:1019400000EB81052F61C5F81880002028626870BF +:1019500006F00F0028702069012800D16F6106F0A1 +:101960000F0028B9227C2946206806F081FD04E09A +:10197000227C2946206806F035FF0020BDE8F08172 +:1019800070B504460D4605F00F006168884201D924 +:10199000012070BD05F0800080280AD105F00F00FD +:1019A00000EBC00104F13C0000EB810601207070E7 +:1019B00007E005EBC50104F51F7000EB8106002070 +:1019C00070700120B07005F00F00307000BF94F807 +:1019D000BC04012801D10220DBE7012084F8BC040B +:1019E00000BF3146206806F0B0FE05F00F0028B9B0 +:1019F000217C04F2C442206806F028FE00BF0020CB +:101A000084F8BC0400BF00BFC3E72DE9F0410446E1 +:101A10000E461746984606F00F0000EBC00104F191 +:101A20003C0000EB81052F61C5F81880002028627A +:101A30000120687006F00F0028702069012800D18D +:101A40006F6106F00F0028B9227C2946206806F055 +:101A50000FFD04E0227C2946206806F0C3FE00202A +:101A6000BDE8F0812DE9FE4F0446D4F800B05E4693 +:101A7000206807F042F9002874D1206807F07CF94B +:101A800008B9BDE8FE8F40F608008059C0F30D206C +:101A9000C4F8FC04206807F06FF900F00200022887 +:101AA00005D12068406900F0020021684861206883 +:101AB00007F062F900F01000102845D12068806915 +:101AC00020F0100021688861DBF8209009F00F00F9 +:101AD00000EBC00104F51F7000EB810AC9F343401D +:101AE00002281AD147F6F07009EA000030B3C9F3B2 +:101AF0000A125846DAF8101007F043F9C9F30A1130 +:101B0000DAF810000844CAF81000C9F30A11DAF82C +:101B100020000844CAF8200010E0C9F3434006281A +:101B20000CD1082204F2C441584607F02AF9C9F33F +:101B30000A11DAF820000844CAF8200020688069F9 +:101B400040F0100021688861206807F015F900F462 +:101B50000020B0F5002F7BD10025206807F0DCF8CD +:101B6000029072E0E1E2029800F00100002868D0E3 +:101B7000E9B2206807F0F3F8804608F0010048B1A8 +:101B8000012106F5306000EB4510816029462046B2 +:101B900002F0F4FE08F00800082809D1082106F533 +:101BA000306000EB451081602946204602F0B4FE0B +:101BB00008F01000102805D1102106F5306000EB68 +:101BC0004510816008F00200022824D1DBF81400DF +:101BD00000F08000802807D140F60400805940F4CE +:101BE000806140F60400815105EBC50104F51F70CA +:101BF00000EB810A9AF80300012806D100208AF838 +:101C00000300E9B2204600F09BFA022106F530609D +:101C100000EB4510816008F02000202805D120212C +:101C200006F5306000EB4510816008F40050B0F517 +:101C3000005F06D14FF4005106F5306000EB45100F +:101C400081606D1C029840080290029800288AD199 +:101C5000206807F091F800F48020B0F5802F7DD146 +:101C6000206807F04FF8029000259AE0029800F0F3 +:101C70000100002873D0E9B2206807F057F88046C9 +:101C800008F00100F0B305F00F0101208840019039 +:101C900040F634008159019821EA000040F63401F1 +:101CA0008851012106F5106000EB45108160206924 +:101CB000012824D105EBC50104F13C0000EB8100B3 +:101CC00005EBC502016904F13C0000EB8200C0682D +:101CD000014405EBC50204F13C0000EB8200016108 +:101CE0006DB905EBC50104F13C0000EB8100806992 +:101CF00028B904F2C4420121206806F0A7FCE9B229 +:101D0000204600E001E0FFF703FD08F00800082886 +:101D100005D1082106F5106000EB4510816008F040 +:101D20001000102805D1102106F5106000EB4510B9 +:101D3000816008F04000402805D1402106F5106080 +:101D400000EB4510816008F0020002281DD12946F1 +:101D5000584606F093FF05EBC50101E025E01CE0C5 +:101D600004F13C0000EB810A9AF80300012806D137 +:101D700000208AF80300E9B2204600F0D8F90221D9 +:101D800006F5106000EB4510816008F080008028A7 +:101D900003D12946204602F093FE6D1C02984008AC +:101DA0000290029800287FF461AF206806F0E4FFFB +:101DB00000F00040B0F1004F1CD140F60400805903 +:101DC00020F0010140F60400815194F8F404012848 +:101DD00007D1002084F8F40400212046FFF764FCBA +:101DE00002E0204600F0D4FA2068406900F000408C +:101DF00021684861206806F0BFFF00F40060B0F57C +:101E0000006F0ED140F60800805900F0010010B1BB +:101E1000204600F015FB2068406900F4006021684E +:101E20004861206806F0A8FF00F48050B0F5805F9C +:101E30007ED140F60400805920F0010140F60400F4 +:101E400081511021206806F019FF002732E04FF67B +:101E50007F3106F5106000EB4710816006F51060D9 +:101E600000EB4710006820F4001106F5106000EB4D +:101E7000471001604FF67F3106F5306000EB4710E8 +:101E8000816006F5306000EB4710006820F4001117 +:101E900006F5306000EB4710016006F5306000EB9E +:101EA0004710006840F0006106F5306000EB471015 +:101EB00001607F1C6068B842C9D840F61C00805998 +:101EC00040F0011140F61C008151206B70B1D6F832 +:101ED000840840F00B01C6F8841840F6440080598D +:101EE00040F00B0140F6440081510FE040F6140031 +:101EF000805942F22B01084340F614018851081F13 +:101F0000805940F00B014FF401608151D6F8000870 +:101F100020F4FE60C6F80008217C04F2C442206868 +:101F200006F094FB2068406900F48050216800E0CE +:101F300000E04861206806F01FFF00F40050B0F593 +:101F4000005F17D1206806F04FF8206806F0C2FE47 +:101F5000E06000F051FC0090227B2068009906F0C0 +:101F600093FF204600F0FCF92068406900F400501F +:101F700021684861206806F0FFFE00F0080008288C +:101F800008D1204600F00BFA2068406900F00800F4 +:101F900021684861206806F0EFFE00F0800080288C +:101FA00018D1DBF8180020F08000CBF818000125CC +:101FB0000DE005EBC50104F51F7000EB8100C07852 +:101FC000012803D1E9B22046FFF7C9FB6D1C606808 +:101FD000A842EED8206806F0CFFE00F48010B0F5DD +:101FE000801F2DD1012522E006F5106000EB451081 +:101FF000D0F8009005EBC50104F13C0000EB810036 +:102000000079012812D109F00040B0F1004F0DD144 +:10201000012105EBC50204F13C0000EB8200C17018 +:10202000E8B240F080012046FFF799FB6D1C606824 +:10203000A842D9D82068406900F48010216848611E +:10204000206806F099FE00F40010B0F5001F44D19E +:10205000012538E006F5306000EB4510D0F800901F +:1020600005EBC50104F51F7000EB81000079012824 +:1020700028D109F00040B0F1004F23D109F480309D +:1020800094F8FC1401F0010188421BD1012105EBF9 +:10209000C50204F51F7000EB8200C170DBF8180068 +:1020A00040F08000CBF81800DBF8140000F080004E +:1020B00040B940F60400805940F4007140F6040035 +:1020C000815103E06D1C6068A842C3D800BF20683E +:1020D000406900F4001021684861206806F04CFE59 +:1020E00000F08040B0F1804F08D12046FFF709FB97 +:1020F0002068406900F0804021684861206806F04F +:102100003BFE00F0040004280FD12068D0F80490B2 +:1021100009F00400042802D12046FFF719FB2068CB +:10212000406840EA09002168486000BFA9E470B532 +:1021300004460D462946D4F8080505F071FA70BD2D +:1021400070B504460D462946D4F8080505F08CFA0A +:1021500070BD70B58AB0044614B901200AB070BDD4 +:10216000266894F8BD0428B9002084F8BC042046F1 +:1021700000F0A2F8032084F8BD04F06B00F4807036 +:1021800008B900212161206806F06AF9282204F1CB +:1021900010016846FEF7D8F894E80F0005F038FF04 +:1021A00020B1022084F8BD040120D7E70021206877 +:1021B00006F017FE002531E0012105EBC50204F110 +:1021C0003C0000EB8200417005EBC50104F13C00CE +:1021D00000F8215005EBC50100EB810005810021CD +:1021E00005EBC50204F13C0000EB8200017105EB38 +:1021F000C50204F13C0000EB8200C16005EBC502A2 +:1022000004F13C0000EB8200016105EBC50204F122 +:102210003C0000EB82008161681CC5B26068A84286 +:10222000CAD800252AE0002105EBC50204F51F707D +:1022300000EB8200417005EBC50104F51F7000F84A +:102240002150002105EBC50200EB8200017105EB76 +:10225000C50204F51F7000EB8200C16005EBC502EA +:1022600004F51F7000EB8200016105EBC50204F567 +:102270001F7000EB82008161681CC5B26068A842D3 +:10228000D1D8282204F110016846FEF75DF894E8E1 +:102290000F0005F0F5FF20B1022084F8BD040120F5 +:1022A0005CE7002084F83800012084F8BD04206831 +:1022B00005F0D4FF002051E710B586B00446142184 +:1022C00001A8FEF768F82068B0F1A04F42D100BF26 +:1022D000002000902048006840F001001E4908607E +:1022E0000846006800F00100009000BF00BF4FF4F6 +:1022F000C05001900220029000200390032004901F +:102300000A20059001A91548FEF7A6FF00BF124854 +:10231000001D006840F080000F49091D086000BFE3 +:10232000002000900C481430006840F480400A49B6 +:10233000143108600846006800F48040009000BF37 +:1023400000BF00BF002205214320FFF75BF94320B7 +:10235000FFF748F906B010BD3038024000000240D7 +:1023600070B504460125E06808B9002506E0E0687C +:10237000022801D1012501E0FEF7BCFC2946D4F872 +:10238000080505F01AFAD4F8080505F0C1F970BD82 +:1023900010B50446D4F8080505F0F0F910BD10B5E5 +:1023A0000446D4F8080505F0F4F910BD70B50446EC +:1023B0000D4600BF94F8BC04012801D1022070BD75 +:1023C000012084F8BC0400BF84F8385029462068F6 +:1023D00006F03BFD00BF002084F8BC0400BF00BF36 +:1023E000EDE710B5044604F2C441D4F8080505F041 +:1023F000FBF910BD70B50446256800BF94F8BC0415 +:10240000012801D1022070BD012084F8BC0400BF66 +:10241000A06A012806D1A069012803D0A86B40F466 +:102420008030A863206806F0F7FB206805F004FF01 +:1024300000BF002084F8BC0400BF00BFE3E7000039 +:1024400010B50446D4F8080505F02BFA2068D0F83A +:10245000000E40F001002168C1F8000E206A28B18A +:102460000348006840F006000149086010BD000004 +:1024700010ED00E008B50120034908620348006838 +:10248000009000BF08BD000000000E420070004038 +:10249000F8B5044600250026207800F0010020B998 +:1024A000207800F0040004282FD100205B498866C2 +:1024B000FEF7E4FF054606E0FEF7E0FF401B0228BA +:1024C00001D90320F8BD56480068C0F3C060002859 +:1024D000F2D160688101207A41EA0070504984316C +:1024E000086001204D498866FEF7C8FF054606E0F2 +:1024F000FEF7C4FF401B022801D90320E2E7484849 +:102500000068C0F3C0600028F2D0207800F002001C +:1025100002287DD100BF0020009041484030006873 +:1025200040F080503E49403108600846006800F0A5 +:102530008050009000BF00BF3A48006840F48070AF +:1025400038490860FEF79AFF054606E0FEF796FF59 +:10255000401B022801D90320B4E73248006800F488 +:1025600080700028F2D02E487030006800F4407669 +:102570004EB3A08900F44070B04224D02848703097 +:10258000006820F440760120274908600020086098 +:10259000234870300660006800F0010098B1FEF733 +:1025A0006DFF054608E0FEF769FF401B41F28831E8 +:1025B000884201D9032085E7194870300068C0F3CC +:1025C00040000028EFD000BFA08900F44070B0F5B3 +:1025D000407F0CD112480830006820F4F810134AEC +:1025E000E168114008430E490831086007E00C48D3 +:1025F0000830006820F4F8100949083108600848DC +:1026000070300068A189C1F30B010843044900E060 +:1026100002E07031086000BF002053E7000047422D +:102620000038024000700040400E4742FFFCFF0FA0 +:1026300070B504460D460CB9012070BD58480068BD +:1026400000F00700A84209D255490D7008460068FD +:1026500000F00700A84201D00120EEE7207800F04A +:10266000020002281DD1207800F00400042805D1C2 +:102670004C48006840F4E0504A490860207800F077 +:102680000800082805D14748006840F460404549E3 +:1026900008604448006820F0F000A1680843414900 +:1026A0000860207800F00100A8B36068012807D115 +:1026B0003C4808380068C0F34040B8B90120BCE786 +:1026C0006068022802D06068032807D135480838BE +:1026D0000068C0F3406048B90120AEE731480838CF +:1026E0000068C0F3400008B90120A6E72D48006843 +:1026F00020F00300616808432A490860FEF7BEFE27 +:10270000064609E0FEF7BAFE801B41F28831884296 +:1027100002D9032091E707E02248006800F00C008E +:102720006168B0EB810FEDD11D48006800F0070033 +:10273000A84209D91A490D700846006800F0070040 +:10274000A84201D0012078E7207800F00400042896 +:1027500007D11448006820F4E050E16808431149AB +:102760000860207800F00800082808D10D480068AB +:1027700020F46040216940EAC1000A49086000F085 +:1027800061F808490968C1F30311074A515CC84060 +:102790000649086006480068FEF7A0FE00204CE7E6 +:1027A000003C024008380240642E0108100000205E +:1027B000080000200F2202600D4A126802F0030296 +:1027C00042600B4A126802F0F0028260084A126806 +:1027D00002F4E052C260064A126802F46042D20873 +:1027E0000261044A126802F007020A6070470000A2 +:1027F00008380240003C0240014800687047000071 +:102800001000002000B5FFF7F7FF04490968C1F385 +:102810008221034A515CC84000BD000008380240D4 +:10282000742E010800B5FFF7E7FF04490968C1F3FA +:102830004231034A515CC84000BD000008380240E4 +:10284000742E01082DE9F047002400250026A1463A +:102850002548006800F00C0020B1042805D00828A5 +:102860003AD105E0DFF8849039E0DFF8849036E073 +:102870001D48001F006800F03F041B48001F00684F +:1028800000F4800078B11A481749091F0968C1F39C +:102890008811A0FB01700146224600233846FDF74F +:1028A000F1FC05460EE011480F49091F0968C1F304 +:1028B0008811A0FB01700146224600233846FDF72F +:1028C000E1FC05460848001F0068C0F30140401CB9 +:1028D0004600B5FBF6F902E0DFF8109000BF00BF3C +:1028E0004846BDE8F0870000083802400024F400A4 +:1028F00000127A00F8B504460CB90120F8BD207822 +:1029000000F00100002874D0F948006800F00C00C5 +:1029100004280DD0F648006800F00C00082813D1F8 +:10292000F348001F006800F48000B0F5800F0BD161 +:10293000EF4808380068C0F34040002859D060686C +:10294000002856D10120D9E700BF6068B0F5803F6C +:1029500008D1E7480838006840F48030E449083975 +:1029600008601EE06068B0F5A02F0DD1E04808387F +:10297000006840F48020DE49083908600846006895 +:1029800040F4803008600CE0D9480838006820F432 +:102990008030D749083908600846006820F4802054 +:1029A000086000BF606890B1FEF768FD054606E06C +:1029B000FEF764FD401B642801D903209EE7CC4844 +:1029C00008380068C0F340400028F1D011E0FEF75D +:1029D00055FD054606E0FEF751FD401B642801D970 +:1029E00003208BE7C24808380068C0F34040002845 +:1029F000F1D1207800F0020002285FD1BC480068C5 +:102A000000F00C0058B1BA48006800F00C0008282B +:102A10001CD1B748001F006800F48000B0B9B4486A +:102A200008380068C0F3400020B1E068012801D0F8 +:102A3000012063E7AE480838006820F0F8002169FB +:102A400040EAC100AA490839086037E0E06800B3ED +:102A50000120A8490860FEF711FD054606E0FEF7D3 +:102A60000DFD401B022801D9032047E7A048083884 +:102A70000068C0F340000028F1D09D480838006885 +:102A800020F0F800216940EAC1009949083908603E +:102A900014E0002097490860FEF7F0FC054606E0C8 +:102AA000FEF7ECFC401B022801D9032026E79048E2 +:102AB00008380068C0F340000028F1D1207800F009 +:102AC000080008282CD16069A8B101208A49086053 +:102AD000FEF7D4FC054606E0FEF7D0FC401B0228BA +:102AE00001D903200AE782486C300068C0F3400037 +:102AF0000028F1D014E000207F490860FEF7BEFCFA +:102B0000054606E0FEF7BAFC401B022801D9032067 +:102B1000F4E677486C300068C0F340000028F1D13B +:102B2000207800F00400042870D100277048383065 +:102B3000006800F0805090B900BF002000906C4801 +:102B40003830006840F080506949383108600846E4 +:102B5000006800F08050009000BF00BF0127674868 +:102B6000006800F48070B0B96448006840F4807078 +:102B700062490860FEF782FC054606E0FEF77EFC2F +:102B8000401B022801D90320B8E65C48006800F425 +:102B900080700028F2D000BFA068012808D15448F6 +:102BA0006830006840F001005149683108601DE05C +:102BB000A06805280DD14E486830006840F0040038 +:102BC0004B49683108600846006840F00100086021 +:102BD0000CE047486830006820F001004449683143 +:102BE00008600846006820F00400086000BFA06884 +:102BF000A8B1FEF743FC054609E0FEF73FFC401B89 +:102C000041F28831884202D9032077E626E038482D +:102C100068300068C0F340000028EED013E0FEF7F3 +:102C20002DFC054608E0FEF729FC401B41F28831E7 +:102C3000884201D9032061E62D4868300068C0F35E +:102C400040000028EFD1012F07D129483830006813 +:102C500020F0805026493831086000BFA069002864 +:102C600045D02348006800F00C0008285DD0A0691A +:102C7000022845D100201F490866FEF7FFFB0546E4 +:102C800006E0FEF7FBFB401B022801D9032035E6D6 +:102C9000174808380068C0F340600028F1D1D4E933 +:102CA00007010843616A40EA81110122A06AC2EB70 +:102CB000500041EA00412C20005D41EA00600C49CF +:102CC000091F086001200B490866FEF7D7FB05467F +:102CD00006E0FEF7D3FB401B022801D903200DE6D6 +:102CE000034808380068C0F340600028F1D049E08C +:102CF0000838024000004742800E47420070004002 +:102D0000002021490866FEF7B9FB054606E0FEF7FC +:102D1000B5FB401B022801D90320EFE51B480068E2 +:102D2000C0F340600028F2D12CE0A069012800D156 +:102D3000E4E51648001D0668A069012820D006F4C5 +:102D40008001E06981421BD106F03F01206A814287 +:102D500016D147F6C0703040616AB0EB811F0FD1C9 +:102D600006F440310122A06AC2EB5000B1EB004FE3 +:102D700006D106F070612C20005DB1EB006F01D030 +:102D80000120BBE50020B9E50000474200380240C1 +:102D900010B50023046804F1500303EB81031A60AB +:102DA00010BD000070B505460B4616460024286885 +:102DB00040680E4900EA0104200CD870C4F30420D6 +:102DC000587004F03F009870C4F3423018705EB938 +:102DD000D87801F0D0FED870587801F0CCFE587049 +:102DE000987801F0C8FE9870002070BD3FFFFF008A +:102DF00070B504460B46164600252068806A586068 +:102E000020680069C0F30E009860206800680E49D1 +:102E100000EA0105C5F305401870C5F30620587097 +:102E200005F07F009870A80DD8705EB9187801F091 +:102E3000A2FE1870587801F09EFE5870987801F044 +:102E40009AFE9870002070BD7F7F7F0070B50446A9 +:102E500001250CB9012070BD607F20B900202077CA +:102E6000204600F045F80220607700BFCA202168A4 +:102E7000486253202168486200BF204601F094FE5A +:102E80000546EDB9206880681849084021688860C7 +:102E900021696068084361690843216889680843BB +:102EA000216888602168E0680861206801692089DC +:102EB00041EA004021680861204601F09AFE05467B +:102EC0006DB92068006C20F48020216808642068B7 +:102ED000006CA1690843216808640120607700BF85 +:102EE000FF202168486200BF2846B4E7BFFF8FFF7C +:102EF0001FB50446002000900190029003900949FC +:102F0000206888420CD102200090C00103906846DE +:102F1000FFF7BEFA08B1FDF7EDFE01200249086097 +:102F20001FBD0000002800403C0E47422DE9F04143 +:102F300005460C4617464FF0000800BF287F0128C1 +:102F400002D10220BDE8F0810120287700BF0220D5 +:102F500068774FB9607800F01000102804D16078CD +:102F600000F0EF000A30607087B9E07801F00EFEE3 +:102F70000304607801F00AFE43EA0023A07801F020 +:102F800005FE0343207843EA403809E0E078000476 +:102F9000617840EA0120A1780843217840EA41386D +:102FA00000BFCA202968486253202968486200BFD0 +:102FB000284601F0F9FD064646B90B4808EA00002C +:102FC00029684860284601F014FE06460EB9012023 +:102FD000687700BFFF202968486200BF00BF00205B +:102FE000287700BF3046ADE73FFFFF002DE9F041F5 +:102FF00004460D4617464FF0000800BF207F012809 +:1030000002D10220BDE8F0810120207700BF02201C +:103010006077CFB92068806800F0400000B102E01E +:103020000020E87000BF287801F0B0FD0304687844 +:1030300001F0ACFD43EA0023A87801F0A7FD0343AB +:10304000E87843EA805812E02068806800F0400089 +:1030500000B102E00020E87000BF28780004697821 +:1030600040EA0120A9780843E97840EA815800BF86 +:10307000CA202168486253202168486200BF204668 +:1030800001F092FD0646B6B9124808EA0000216830 +:1030900008602068806820F4802021688860D5E975 +:1030A0000301084321688968084321688860204635 +:1030B00001F09FFD06460EB90120607700BFFF209A +:1030C0002168486200BF00BF0020207700BF304663 +:1030D00098E700007F7F7F0070B5044600252068D8 +:1030E000C06820F0A0002168C860FEF7C7F9054657 +:1030F00007E0FEF7C3F9401BB0F57A7F01D9032042 +:1031000070BD2068C06800F020000028F1D00020C9 +:10311000F6E70000F0B589B004460E46002703200C +:1031200084F83400606C032820D0B6F5805F04D1A9 +:10313000A06B40F08050A0631CE0B6F5006F07D193 +:10314000204602F0E7FB0546A06B2843A06311E090 +:103150003EB9204602F0AAFB0546A06B2843A063B7 +:1031600008E0A06B40F00060A06303E0A06B40F0BB +:103170008050A063A06B38B1174821688863012094 +:1031800084F83400012713E060680390A06804907D +:10319000E0680590069660690790A069089006A807 +:1031A00007C88DE80700206803A90EC901F05DFD7E +:1031B0004FF40071206801F0C9FD054635B106489D +:1031C00021688863A06B2843A0630127012084F84D +:1031D0003400384609B0F0BDFF05400070470000DC +:1031E00010B50246506E800F0870506EC0F38360B9 +:1031F0004870506EC0F301608870506E000CC8704B +:10320000B2F86400000A087192F864004871906E88 +:10321000000DC880906EC0F3034008726820805A89 +:10322000C0F3C03048726820805AC0F38030887282 +:103230006820805AC0F34030C8726820805AC0F3BA +:103240000030087300204873506C002836D1682085 +:10325000805A8005030DD06E43EA90700861D06EED +:10326000C0F3C2600875D06EC0F302604875D06EBE +:10327000C0F342508875D06EC0F38240C875D06EDE +:10328000C0F3C23008760869401C50650B7E506D53 +:1032900003F007039B1C01249C4060435065087A9F +:1032A00000F00F03012098409065D2E915035B0AF6 +:1032B0005843D0654FF40073136621E0506C012829 +:1032C00013D16820805C8006830AD06E43EA1040E8 +:1032D00008610869401C83025365536DD3654FF440 +:1032E00000739365936D13660AE02E481368986324 +:1032F000906B40F080509063012082F8340010BD44 +:103300006C20805AC0F3803001F8190F6C20805A6D +:10331000C0F3C61048706C20805C00F07F0088709D +:10332000106FC00FC870106FC0F341700871106F3C +:10333000C0F382604871106FC0F383508871106FC2 +:10334000C0F34050C87100200872106FC0F30040F5 +:1033500048727020805AC0F3C03088727020805A42 +:10336000C0F38030C8727020805AC0F340300873B8 +:103370007020805AC0F3003048737020805AC0F328 +:10338000812088737020805AC0F30120C873702098 +:10339000805CC0F34600087401204874193900208D +:1033A000ADE70000FF0540000246506C0860906CDD +:1033B0004860D06C8860106DC860506D0861906D79 +:1033C0004861D06D8861106EC86100207047F8B503 +:1033D0000446002000906946204602F04FFA054658 +:1033E00015B1A06B2843A0630098C0F34326304674 +:1033F000F8BD10B504460CB9012010BD94F8340096 +:1034000020B900202077204600F06AF8032084F8D5 +:103410003400204600F00CF808B10120EDE7002050 +:10342000A0632063012084F834000020E5E7000059 +:1034300070B58AB00446002004900590069007906D +:1034400008907620099007A807C88DE80700206833 +:1034500004A90EC901F009FC064616B101200AB004 +:1034600070BD00201C490860206801F018FC012094 +:103470001949A039C1F8A0000220FDF7D9FE204665 +:1034800002F096F905463DB1012084F83400A06BA6 +:103490002843A0630120E2E7204602F007F9054631 +:1034A0003DB1012084F83400A06B2843A0630120C3 +:1034B000D5E74FF40071206801F048FC05464DB196 +:1034C000064821688863A06B2843A063012084F824 +:1034D0003400C4E70020C2E7A0802542FF05400079 +:1034E00010B586B00446142101A8FCF754FF5449D6 +:1034F000206888427ED100BF0020009051480068BB +:1035000040F400604F4908600846006800F400601D +:10351000009000BF00BF00BF002000904948143851 +:10352000006840F004004749143908600846006804 +:1035300000F00400009000BF00BF00BF002000901A +:103540000846006840F0080008600846006800F07F +:103550000800009000BF00BF4FF4F8500190022017 +:10356000029001200390022004900C20059001A9F4 +:103570003548FDF771FE04200190022002900120E1 +:103580000390022004900C20059001A92F48FDF71C +:1035900063FE2F482F4908604FF00060486000210B +:1035A0002C488160C1604FF48061016189004161F4 +:1035B000890081612021C1610021016204214162F1 +:1035C000032181624FF40001C16289100163FDF79C +:1035D0006FFD08B1FDF78EFB00BF1E4820648463B9 +:1035E00000BF1B4848301C4908604FF0006048602D +:1035F000402100E021E0184881600021C1604FF4C3 +:103600008061016189004161890081612021C1617E +:103610000021016204214162032181624FF4000113 +:10362000C16289100163FDF743FD08B1FDF762FB3C +:1036300000BF0948E063846300BF06B010BD00000E +:10364000002C01404438024000080240000C0240B7 +:10365000586402404C050020AC0500202DE9F043E1 +:1036600087B004460F4691461D46C8463FB9A06B39 +:1036700040F00060A063012007B0BDE8F08394F83B +:10368000340001287ED10020A06308EB0501E06D25 +:10369000814205D9A06B40F00070A0630120EBE7E8 +:1036A000032084F8340000202168C8622068C06BC1 +:1036B00040F22A3108432168C8633848216CC86346 +:1036C0003748216CC8640020216C08650021206CFB +:1036D0008160206C0068006820F0C000216C89685F +:1036E0000843216C096808606A029308226802F1A5 +:1036F00080013A46206CFDF751FD80B12068C06B17 +:1037000020F495702168C863264821688863A06BFF +:1037100040F08040A063012084F83400ACE7012031 +:1037200021490860606C012801D04FEA48284FF019 +:10373000FF300190680202909020039002200490D4 +:10374000002005900120069001A9206801F068FA88 +:10375000012D07D9822020634146206801F05EFBDD +:10376000064606E0812020634146206801F072FB96 +:10377000064676B10B4821688863A06B3043A0638E +:10378000012000E007E084F83400002020630120DD +:1037900072E7002070E702206EE700001155000874 +:1037A0009D540008FF0540008C85254210B5044655 +:1037B000FDF766F910BD00002DE9F04387B004461F +:1037C000884691461D464F46B8F1000F07D1A06BC1 +:1037D00040F00060A063012007B0BDE8F08394F8DA +:1037E0003400012874D10020A0637919E06D814272 +:1037F00005D9A06B40F00070A0630120ECE7032026 +:1038000084F8340000202168C8622068C06B40F250 +:103810001A2108432168C8633848E16BC8633848F7 +:10382000E16BC8640020E16B0865606C012800D082 +:103830007F02012D07D9A02020633946206801F0BE +:10384000E7FB064606E0902020633946206801F039 +:10385000FBFB064666B12B4821688863A06B3043AA +:10386000A063012084F83400002020630120B3E726 +:103870000120254908604021E06B8160E06B006811 +:10388000006820F0C000E16B89680843E16B0968BB +:10389000086069028B08216801F180024146E06BF3 +:1038A000FDF77CFCA8B12068C06B40F21A21884368 +:1038B0002168C863134821688863A06B40F080408A +:1038C000A063012084F8340000202063012083E7F6 +:1038D00011E04FF0FF3001906802029090200390B9 +:1038E0000020049005900120069001A9206801F0B5 +:1038F00097F9002070E702206EE700005955000894 +:103900009D540008FF0540008C85254210B50446F3 +:103910000CB9012010BD606A38B96068B0F5827FCB +:1039200000D105E00021E16102E000212161616137 +:103930000021A16294F8510028B9002084F85000B9 +:10394000204600F047F8022084F851002068006803 +:1039500020F0400021680860A08800F4827021896E +:1039600001F404410843A18901F400610843217C6A +:1039700001F002010843217D01F001010843218B80 +:1039800001F400710843217F01F038010843202130 +:10399000095D01F080010843218D01F400510843C5 +:1039A000216808600421A06901EA104094F82410FD +:1039B00001F010010843216848602068C06920F4C4 +:1039C00000602168C86100206065012084F8510012 +:1039D00000209FE710B586B00446142101A8FCF72B +:1039E000DAFC1B49206888422FD100BF00200090DC +:1039F0001848006840F4004016490860084600680E +:103A000000F40040009000BF00BF00BF0020009005 +:103A100010481038006840F002000E491039086064 +:103A20000846006800F00200009000BF00BF382088 +:103A300001900220029000200390032004900620B1 +:103A4000059001A90448FDF707FC06B010BD000071 +:103A5000003C004040380240000402402DE9FF5F76 +:103A60000446884691461D460E9E01200290002085 +:103A7000019000BF94F85000012803D1022004B047 +:103A8000BDE8F09F012084F8500000BFFDF7F6FC70 +:103A9000074694F851B060680390AA46BBF1010F45 +:103AA0000BD00398B0F5827F04D1A06810B9BBF1A8 +:103AB000040F02D002200190DBE0B8F1000F03D028 +:103AC000B9F1000F00D015B901200190D1E094F8B0 +:103AD0005100042802D0052084F8510000206065C0 +:103AE000C4F83890E587A587C4F83080E586A586B8 +:103AF000206460642068006800F04000402805D021 +:103B00002068006840F0400021680860E068B0F577 +:103B1000006F4AD1606810B1BAF1010F09D1206B72 +:103B200000882168C860206B801C2063E08E401EE6 +:103B3000E08633E02068806800F00200022810D19F +:103B4000E08E70B1029801280BD1206B00882168AB +:103B5000C860206B801C2063E08E401EE086002041 +:103B600002902068806800F0010068B1E08F58B1D1 +:103B70002068C068A16B0880A06B801CA063E08FE8 +:103B8000401EE08701200290FDF778FCC01BB04288 +:103B900004D3701C10B1032001906AE0E08E00286D +:103BA000C8D1E08F0028C5D14AE0606810B1BAF1F1 +:103BB000010F09D1206B007821680873206B401C2D +:103BC0002063E08E401EE08634E02068806800F0CC +:103BD0000200022810D1E08E70B1029801280BD1AA +:103BE000206B007821680873206B401C2063E08EF6 +:103BF000401EE086002002902068806800F00100EE +:103C000068B1E08F58B12068C068A16B0870A06BE4 +:103C1000401CA063E08F401EE08701200290FDF76A +:103C20002DFCC01BB04201D3701C00B916B9032093 +:103C300001901EE0E08E0028C7D1E08F0028C4D19B +:103C40003A463146204601F08DFF20B10120019017 +:103C5000202060650DE0A06850B900BF00200090F2 +:103C60002068C068009020688068009000BF00BF96 +:103C700000BF012084F8510000BF002084F85000EC +:103C800000BF0198FBE67047704710B504460CB9B9 +:103C9000012010BD94F83D0028B9002084F83C00B4 +:103CA000204600F025F8022084F83D00211D206800 +:103CB00002F09CF8012084F8460000BF84F83E0022 +:103CC00001213F200155402001554120015500BFF1 +:103CD00000BF012084F842004320015544200155D3 +:103CE0004520015500BF012084F83D000020D0E7A9 +:103CF00070470000014691F83D00012801D00120E5 +:103D00007047022081F83D000868C06840F001005B +:103D10000B68D8601A4B086898421BD00868B0F14D +:103D2000804F17D0174B0868984213D0164B08687D +:103D300098420FD0154B086898420BD0144B086876 +:103D4000984207D0134B0868984203D0124B08687A +:103D500098420CD10868806800F00702062A0CD04F +:103D60000868006840F001000B68186005E008680A +:103D7000006840F001000B6818600020C0E70000F8 +:103D8000000001400004004000080040000C00401A +:103D9000000401400040014000180040704710B589 +:103DA000044620680069C0F34000D8B12068C068AC +:103DB000C0F34000B0B16FF002002168086101203B +:103DC00020772068806900F0030018B12046FFF7D3 +:103DD000E5FF05E0204600F0ADF8204600F0ABF826 +:103DE0000020207720680069C0F38000D8B12068E7 +:103DF000C068C0F38000B0B16FF0040021680861B2 +:103E0000022020772068806900F4407018B12046B5 +:103E1000FFF7C4FF05E0204600F08CF8204600F0D4 +:103E20008AF80020207720680069C0F3C000D8B16C +:103E30002068C068C0F3C000B0B16FF0080021680E +:103E40000861042020772068C06900F0030018B1E1 +:103E50002046FFF7A3FF05E0204600F06BF8204660 +:103E600000F069F80020207720680069C0F3001096 +:103E7000D8B12068C068C0F30010B0B16FF0100076 +:103E800021680861082020772068C06900F440702C +:103E900018B12046FFF782FF05E0204600F04AF8FF +:103EA000204600F048F8002020772068006900F0E4 +:103EB000010058B12068C06800F0010030B16FF017 +:103EC000010021680861204600F036F8206800698A +:103ED000C0F3C01058B12068C068C0F3C01030B142 +:103EE0006FF08000216808612046FFF7CCFE206853 +:103EF0000069C0F3801058B12068C068C0F380101A +:103F000030B16FF0400021680861204600F020F8D1 +:103F100020680069C0F3401058B12068C068C0F341 +:103F2000401030B16FF02000216808612046FFF793 +:103F3000ABFE10BD7047704710B5044603492068BA +:103F4000884201D1FDF7A0FA10BD0000001000402A +:103F500070477047704700002DE9F84F044620680D +:103F600005682068C668206847694FF00009CA469E +:103F700005F00F09B9F1000F0AD105F0200038B1A2 +:103F800006F0200020B1204602F08FF8BDE8F88F3F +:103F9000B9F1000F7CD007F0010018B906F4907059 +:103FA000002875D005F0010030B106F4807018B11A +:103FB000206C40F00100206405F0040030B107F0EF +:103FC000010018B1206C40F00200206405F00200EE +:103FD00030B107F0010018B1206C40F004002064FB +:103FE00005F0080048B106F0200010B907F0010004 +:103FF00018B1206C40F008002064206C002846D0E6 +:1040000005F0200028B106F0200010B1204602F093 +:104010004CF820684069C0F3801A206C00F008005A +:1040200010B9BAF1000F2DD0204601F0E5FF20684D +:10403000406900F04000402820D100BF00BF216847 +:10404000143151E8001F21F040002168143141E88B +:104050000002002AF3D100BFA06B50B17548A16BDC +:104060000865A06BFCF7ECFE88B1A06B016D88477A +:104070000DE02046FFF76EFF09E009E02046FFF75C +:1040800069FF04E02046FFF765FF002020647DE71C +:10409000206B012876D105F01000002872D006F0C0 +:1040A00010000028FAD000BF0020009020680068AF +:1040B000009020684068009000BF00BF2068406901 +:1040C00000F0400040285ED1A06B006840681FFAF5 +:1040D00080F8B8F1000F54D0A08D404551DDA4F810 +:1040E0002E80A06BC069B0F5807F43D000BF00BFB9 +:1040F00021680C3151E8001F21F4807021680C31D7 +:1041000041E80002002AF3D100BF00BF00BF2168D0 +:10411000143151E8001F21F001002168143141E8F9 +:104120000002002AF3D100BF00BF00BF2168143194 +:1041300051E8001F21F040002168143141E80002DD +:10414000002AF3D100BF202084F83E000020206325 +:1041500000BF00BF21680C3151E8001F21F01000A2 +:1041600021680C3141E80002002AF3D100BFA06BA6 +:10417000FCF710FEA08DE28D801A81B22046FFF779 +:10418000E8FE03E740E0A08DE18D401A1FFA80F8B9 +:10419000E08DC0B3B8F1000F35D000BF00BF21687B +:1041A0000C3151E8001F21F4907021680C3141E876 +:1041B0000002002AF3D100BF00BF00BF2168143104 +:1041C00051E8001F21F001002168143141E800028C +:1041D000002AF3D100BF202084F83E000020206395 +:1041E00000BF00BF21680C3151E8001F21F0100012 +:1041F00021680C3141E80002002AF3D100BF41469A +:104200002046FFF7A6FEC1E605F0800030B106F0BB +:10421000800018B1204602F043F9B7E605F04000EF +:1042200030B106F0400018B1204601F01BFFADE6AA +:1042300000BFABE6C55E000810B504460CB901200E +:1042400010BDA06900B100E000BF94F83D0028B99E +:10425000002084F83C00204600F028F8242084F850 +:104260003D002068C06820F400502168C8602046E6 +:1042700001F098FF2068006920F4904021680861EF +:104280002068406920F02A00216848612068C068E1 +:1042900040F400502168C86000202064202084F889 +:1042A0003D0084F83E000020CAE7000010B586B04B +:1042B0000446142101A8FCF76EF83D4920688842A5 +:1042C00074D100BF002000903A48006840F0100010 +:1042D000384908600846006800F01000009000BFF0 +:1042E00000BF00BF0020009032481438006840F042 +:1042F00001003049143908600846006800F00100E8 +:10430000009000BF00BF4FF4C060019002200290F7 +:1043100000200390032004900720059001A926485F +:10432000FCF79AFF2548264908604FF00060486076 +:10433000002123488160C1604FF480610161002148 +:1043400041618161C16101624162FCF7B1FE08B166 +:10435000FCF7D0FC00BF1A48A063846300BF174875 +:104360007830184908604FF00060486040211548D7 +:1043700081600021C1604FF48061016100214161D1 +:104380008161C16101624162FCF792FE08B1FCF7F4 +:10439000B1FC00BF0B486063846300BF00220521AD +:1043A0002520FDF72FF92520FDF71CF906B010BDDB +:1043B00000100140443802400000024040640240C6 +:1043C000A80600200807002070B504460D461646D2 +:1043D00094F83E00202816D105B10EB9012070BD19 +:1043E00000BF94F83C00012801D10220F7E701202A +:1043F00084F83C0000BF0020206332462946204656 +:1044000001F0E6FFEBE70220E9E7704770472DE98E +:10441000F84F04460E46174699464FF0000A94F8A6 +:104420003D0020285AD106B117B90120BDE8F88F08 +:1044300000BF94F83C00012801D10220F6E70120DA +:1044400084F83C0000BF00202064212084F83D0057 +:10445000FDF714F88246A784E784A068B0F5805F72 +:1044600004D1206910B90025B04602E035464FF06E +:10447000000800BF002084F83C0000BF1BE053464A +:10448000002280212046CDF8009002F039F808B1D2 +:104490000320CBE745B9B8F80000C0F30800216855 +:1044A000486008F1020803E02878216848606D1C24 +:1044B000E08C401EE084E08C0028E0D153460022CE +:1044C00040212046CDF8009002F01AF808B10320F0 +:1044D000ACE7202084F83D000020A7E70220A5E7F4 +:1044E000704700BFFEE730B50B46002100BF16E065 +:1044F0000A24B4EB107F05D9302404EB107403F8C0 +:10450000114005E0412404EB10740A3C03F811400B +:10451000000100254C00641C1D554C1CE1B2914269 +:10452000E6DB30BD08B500BF0020009016480068EB +:1045300040F48000144908600846006800F48000D8 +:10454000009000BF00BF002205213A20FDF75AF875 +:104550003A20FDF747F800220F213B20FDF752F8E3 +:104560003B20FDF73FF800220F214520FDF74AF8D8 +:104570004520FDF737F8002205214620FDF742F8D7 +:104580004620FDF72FF808BD3038024010B503492A +:104590000348FCF7B2FB0349087010BDDD000020A2 +:1045A000782F0108DC00002000B587B01C220649E6 +:1045B0006846FBF7C9FE0021684606F015FD034971 +:1045C000086007B000BD0000402E01080000002078 +:1045D00000B587B0142102A8FBF7DDFE00BF002064 +:1045E00001907F48006840F010007D49086008464F +:1045F000006800F01000019000BF00BF00BF002065 +:1046000001900846006840F0040008600846006811 +:1046100000F00400019000BF00BF00BF0020019027 +:104620000846006840F0200008600846006800F076 +:104630002000019000BF00BF00BF0020019008468D +:10464000006840F0800008600846006800F08000C4 +:10465000019000BF00BF00BF002001900846006825 +:1046600040F0010008600846006800F00100019079 +:1046700000BF00BF00BF002001900846006840F066 +:10468000020008600846006800F00200019000BFC8 +:1046900000BF00BF002001900846006840F04000C5 +:1046A00008600846006800F04000019000BF00BFAD +:1046B00000BF002001900846006840F00800086034 +:1046C0000846006800F00800019000BF00BF00220B +:1046D0004FF400514348FCF7CBFE00224FF4C05189 +:1046E0004148FCF7C5FE4FF6FF700290032003908F +:1046F0000020049002A93D48FCF7AEFD4FF40050A5 +:1047000002900120039000200490059002A93548F2 +:10471000FCF7A2FD4FF6FF700290032003900020EB +:10472000049002A93248FCF797FDFF200290032075 +:1047300003900020049002A92A48FCF78DFD48F25E +:10474000FF100290032003900020049002A9294842 +:10475000FCF782FD4FF6C730029003200390002043 +:10476000049002A92448FCF777FD4FF6FF700290F1 +:10477000032003900020049002A92048FCF76CFD60 +:104780004FF48060029000200390049002A91A4820 +:10479000FCF762FD4CF2FB700290032003900020B6 +:1047A000049002A91048FCF757FD4FF4C050029046 +:1047B0000120039000200490059002A90A48FCF70C +:1047C0004BFD4FF4005002904FF4881003900020EE +:1047D000049002A90448FCF73FFD07B000BD0000AB +:1047E0003038024000080240000C02400010024035 +:1047F0000014024000000240000402400018024081 +:1048000010B50A480A490860002048607F2108481E +:104810008160FF21C1600021016141618161FEF77A +:1048200015FB08B1FCF766FA10BD00000028004037 +:10483000A80400207047000010B50E480E4908601B +:104840004FF48270486000210B488160C1600161B3 +:1048500041614FF4007181610021C16101624162D7 +:1048600081620A21C162FFF751F808B1FCF742FAF0 +:1048700010BD0000003C00400C06002010B50B48A5 +:104880000B4908604FF4E13048600021084881601E +:10489000C16001610C21416100218161C161FFF7AB +:1048A000CBFC08B1FCF726FA10BD00000010014057 +:1048B0006406002010B500220D490E4802F0F9FCF4 +:1048C00008B1FCF717FA0C490A4803F027F808B1B9 +:1048D000FCF710FA0949074802F0FAF808B1FCF7AA +:1048E00009FA044803F01CF908B1FCF703FA10BDFB +:1048F000E40000203008012058010020340100208D +:1049000000BFFEE700BFFEE710B50248FDF7AAF8BA +:1049100010BD00000C1D01202DE9F04704460D4696 +:1049200026683746D6F8408007F5306000EB451022 +:10493000D0F80890104880450BD909F40040B0F534 +:10494000004F06D14FF4004107F5306000EB4510F1 +:1049500081602046FDF745FD0748804508D920695C +:10496000012805D104F2C4420121206803F06EFE43 +:104970000020BDE8F08700000A30544F2DE9F047D1 +:1049800005460C46D5F800904E46D9F840A006F5ED +:10499000306000EB4410D0F808802869012855D118 +:1049A00008F0080008280FD1434882450BD908F4C5 +:1049B0000040B0F5004F7BD14FF4004106F5306068 +:1049C00000EB4410816073E008F02000202806D13D +:1049D000202106F5306000EB4410816068E008F0AB +:1049E0002800002864D1344882450CD908F40040DE +:1049F000B0F5004F07D14FF4004106F5306000EBF1 +:104A00004410816054E004EBC40105F51F7000EB15 +:104A1000810706F5306000EB4410F9690069C0F3C6 +:104A20001200081A386264B9B86930B905F2C44294 +:104A30000121286803F00AFE03E0396A3869084456 +:104A40003861E1B22846FCF773FE31E01B4882452D +:104A50001BD108F40040B0F5004F07D14FF40041DE +:104A600006F5306000EB4410816021E008F0200082 +:104A7000202805D1202106F5306000EB441081602C +:104A8000E1B22846FCF754FE12E06CB904EBC40115 +:104A900005F51F7000EB8100806928B905F2C4425A +:104AA0000021286803F0D2FDE1B22846FCF740FE61 +:104AB0000020BDE8F08700000A30544F0A31544FFF +:104AC0002DE9F84F07460E46D7F80090C84606EB8A +:104AD000C60107F13C0000EB8104A169206A88420D +:104AE00002D90120BDE8F88F216AA069451AE06863 +:104AF000A84200D2E568E81C4FEA900A17E0216A54 +:104B0000A069451AE068A84200D2E568E81C4FEAAF +:104B1000900A387CABB2F2B200904846216904F0AA +:104B200027FA206928442061206A2844206208F579 +:104B3000106000EB4610806980B2504506D3A16931 +:104B4000206A884202D2A0690028D8D1216AA069CF +:104B500088420ED806F00F01012000FA01FB40F652 +:104B6000340050F8080020EA0B0040F6340141F808 +:104B700008000020B6E7014600BF080900EB8000EE +:104B8000420001F00F001044C0B2704701460022FD +:104B900004E0501CC2B2A1F10A00C1B20A29F8D245 +:104BA000100741EA1060704770B5044600260025E2 +:104BB0002068C06800F04000C8B92068C06840F0B4 +:104BC00080002168C860FCF759FC064608E0FCF745 +:104BD00055FC801BB0F57A7F02D90420607701254F +:104BE0002068C06800F0400008B9012DEFD12846C8 +:104BF00070BD70B5044600252068C06820F08000B4 +:104C00002168C8602068806800F0200030B9204624 +:104C1000FEF762FA10B1042060770125284670BDC6 +:104C200010B5024600230868506248689062D1E9D6 +:104C3000020420430C6920434C6920430343D06A9B +:104C400020F0F7001843D062002010BD014608692B +:104C5000C0B270470146086800F003007047024682 +:104C600002F114004318186870470FB410B50446D9 +:104C70000021DDE903021043059A1043069A104310 +:104C8000079A1043089A10430143606847F6FF6291 +:104C9000904308436060002010BC5DF814FB01469F +:104CA00003200860002070470146D1F8800070475B +:104CB00010B50246002308689060D1E90104204342 +:104CC000CC6820430C6920430343D0686FF30B008A +:104CD0001843D060002010BD70B585B005460C4665 +:104CE00000943720019040200290002003904FF460 +:104CF0008060049069462846FFF7DAFF41F2883267 +:104D00003721284600F0DCF90646304605B070BD74 +:104D100070B585B005460C460B482043009029200D +:104D2000019040200290002003904FF48060049096 +:104D300069462846FFF7BCFF284600F0C9FA064638 +:104D4000304605B070BD00000000108070B585B021 +:104D500005460C460094102001904020029000204F +:104D600003904FF48060049069462846FFF7A0FF47 +:104D700041F288321021284600F0A2F9064630465A +:104D800005B070BD70B585B005460C460094062090 +:104D9000019040200290002003904FF48060049026 +:104DA00069462846FFF784FF41F2883206212846EB +:104DB00000F086F90646304605B070BD30B585B0C6 +:104DC0000446002000900190029003904FF4806010 +:104DD000049069462046FFF76BFF204600F050F92B +:104DE0000546284605B030BD30B585B004464FF4C1 +:104DF000D570009008200190402002900020039080 +:104E00004FF48060049069462046FFF751FF20462A +:104E100000F0E6FA0546284605B030BD70B585B00D +:104E200005460C460094122001904020029000207C +:104E300003904FF48060049069462846FFF738FFDE +:104E400041F288321221284600F03AF906463046EF +:104E500005B070BD70B585B005460C4600941120B4 +:104E6000019040200290002003904FF48060049055 +:104E700069462846FFF71CFF41F288321121284677 +:104E800000F01EF90646304605B070BDF0B585B09D +:104E9000064614461D4600940720019040200290CB +:104EA000002003904FF48060049069463046FFF77D +:104EB000FFFE41F288320721304600F001F9074633 +:104EC000384605B0F0BD30B585B0044600200090EE +:104ED00002200190C0200290002003904FF48060D7 +:104EE000049069462046FFF7E3FE204600F0BEF935 +:104EF0000546284605B030BD70B585B005460C4660 +:104F0000009409200190C0200290002003904FF4EB +:104F10008060049069462846FFF7CAFE284600F0E4 +:104F2000A5F90646304605B070BD30B585B00446DB +:104F30000020009033200190402002900020039038 +:104F40004FF48060049069462046FFF7B1FE41F2BD +:104F500088323321204600F0B3F80546284605B0D4 +:104F600030BD70B585B005460C4600940D2001900B +:104F700040200290002003904FF480600490694626 +:104F80002846FFF795FE41F288320D21284600F0B1 +:104F900097F80646304605B070BD70B585B0054639 +:104FA0000C46002000900320019040200290002039 +:104FB00003904FF48060049069462846FFF778FE1E +:104FC00022460321284600F0AFF90646304605B0D8 +:104FD00070BD000030B585B00446002000900C2064 +:104FE000019040200290002003904FF480600490D4 +:104FF00069462046FFF75CFE044A0C21204600F07B +:105000005FF80546284605B030BD000000E1F50513 +:1050100070B585B005460C460094192001904020DB +:105020000290002003904FF4806004906946284667 +:10503000FFF73EFE41F288321921284600F040F881 +:105040000646304605B070BD70B585B005460C46C5 +:1050500000941820019040200290002003904FF40B +:105060008060049069462846FFF722FE41F28832AC +:105070001821284600F024F80646304605B070BDD9 +:1050800001460E480068C0084FF47A73B0FBF3F095 +:1050900041F2883300FB03F200BF101EA2F10102AF +:1050A00002D14FF000407047486B00F080000028AC +:1050B000F3D0C52088630020F5E700001000002031 +:1050C0002DE9F04305460F46904666480068C00843 +:1050D0004FF47A71B0FBF1F000FB08F900BFB9F1B1 +:1050E0000000A9F1010903D14FF00040BDE8F083B1 +:1050F0006E6B06F045000028F1D006F40060002831 +:10510000EDD1686B00F0040010B10420A863EDE756 +:10511000686B00F0010010B10120A863E6E7C5202C +:10512000A8632846FFF792FDB84201D00120DDE7D1 +:1051300000212846FFF793FD04464B48204008B95C +:105140000020D3E704F00040B0F1004F02D14FF04F +:105150000070CBE704F08040B0F1804F01D14020D7 +:10516000C4E704F00050B0F1005F01D18020BDE73A +:1051700004F08050B0F1805F02D14FF48070B5E749 +:1051800004F00060B0F1006F02D14FF40070ADE7A1 +:1051900004F08060B0F1806F02D14FF48060A5E729 +:1051A00004F08070B0F1807F02D14FF400609DE781 +:1051B00004F40000B0F5000F02D14FF4805095E7E1 +:1051C00004F48000B0F5800F02D14FF400508DE759 +:1051D00004F40010B0F5001F02D14FF4804085E7C1 +:1051E00004F48010B0F5801F02D14FF400407DE739 +:1051F00004F48020B0F5802F02D14FF4003075E721 +:1052000004F40030B0F5003F02D14FF480206DE788 +:1052100004F48030B0F5803F02D14FF4002065E700 +:1052200004F40040B0F5004F02D14FF480105DE768 +:1052300004F48040B0F5804F02D14FF4001055E7E0 +:1052400004F40050B0F5005F02D14FF480004DE748 +:1052500004F00800082801D1000547E74FF480302A +:1052600044E700001000002008E0FFFD10B50146F3 +:1052700016480068C0084FF47A74B0FBF4F041F2AD +:10528000883400FB04F300BF181EA3F1010302D110 +:105290004FF0004010BD4A6B02F045000028F3D0EB +:1052A00002F400600028EFD1486B00F0040010B158 +:1052B00004208863EEE7486B00F0010010B1012084 +:1052C0008863E7E7C52088630020E3E7100000203B +:1052D00010B5014613480068C0084FF47A74B0FB5B +:1052E000F4F041F2883400FB04F300BF181EA3F170 +:1052F000010302D14FF0004010BD4A6B02F045009F +:105300000028F3D002F400600028EFD1486B00F0D1 +:10531000040010B104208863EEE7C52088630020F4 +:10532000EAE70000100000202DE9F04304460F4694 +:1053300090462A480068C0084FF47A71B0FBF1F03B +:1053400041F2883100FB01F900BFB9F10000A9F179 +:10535000010903D14FF00040BDE8F083666B06F011 +:1053600045000028F1D006F400600028EDD1606B04 +:1053700000F0040010B10420A063EDE7606B00F0C2 +:10538000010010B10120A063E6E72046FFF75EFCB4 +:10539000B84201D00120DFE7C520A06300212046EC +:1053A000FFF75DFC054605F4604020B9280CA8F81D +:1053B00000000020D0E705F48040B0F5804F02D116 +:1053C0004FF40050C8E705F40040B0F5004F02D19B +:1053D0004FF48050C0E74FF48030BDE7100000204C +:1053E00010B5014618480068C0084FF47A74B0FB45 +:1053F000F4F041F2883400FB04F300BF181EA3F15F +:10540000010302D14FF0004010BD4A6B02F045008D +:105410000028F3D002F400600028EFD1486B00F0C0 +:10542000040010B104208863EEE7486B00F001002F +:1054300010B101208863E7E7486B00F0400008B135 +:10544000402088630020DFE71000002010B50446EC +:10545000012007490870FBF7CFFA28B90448007803 +:1054600020F00100024908700148007810BD0000DA +:10547000D400002070B5044605F01AFD054604E08E +:10548000FBF7BAFA08B9002070BD05F011FD401B0A +:10549000A042F5D34FF0FF30F6E700002DE9F041D0 +:1054A0000646B46B3046FBF7DFFC02282CD0206C9C +:1054B000476DE06BD0F85480012F02D0B8F1010F96 +:1054C0001FD11248216888632068C06B20F49D704A +:1054D0002168C863A06B40F08040A0632046FDF7C0 +:1054E00076FF0546062D01D0052D05D12068FFF772 +:1054F00071FDA16B0843A063012084F834000020F3 +:1055000020632046FDF76AFEBDE8F081FF054000FC +:1055100070B50646B46B206B82280AD12068FFF76D +:1055200059FD05462DB1A06B2843A0632046FDF729 +:1055300055FE2068C06A20F008002168C86240F269 +:105540003A5021688863012084F8340000202063E9 +:105550002046FEF72BF970BD0146886B0268D26BBE +:1055600042F480720368DA6370472DE9F04389B032 +:1055700004460F46FBF782FF81464FF000080020EB +:10558000019002903E4608212068FFF7DFFB0546A8 +:105590001DB1284609B0BDE8F0835022125B11040A +:1055A0002068FFF799FB05460DB12846F2E74FF05A +:1055B000FF300390082004903020059002200690D0 +:1055C000002007900120089003A92068FFF728FB1E +:1055D0002068FFF7AAFC05460DB12846DAE71CE073 +:1055E0002068406B00F4001040B12068FFF75CFBBE +:1055F00001A941F8280008F1010805E02068406B86 +:1056000000F4005000B90EE0FBF738FFA0EB0900F2 +:10561000401C10B94FF00040BCE72068406B00F020 +:105620002A000028DCD000BF2068406B00F0080092 +:1056300018B1082021688863ACE72068406B00F04F +:10564000020018B1022021688863A3E72068406B3C +:1056500000F0200018B12020216888639AE740F20A +:105660003A502168886302980006029901F47F414C +:1056700040EA0120029901F47F0140EA11200299D9 +:1056800040EA11603060361D01980006019901F46E +:105690007F4140EA0120019901F47F0140EA112095 +:1056A000019940EA11603060002073E730B58FB097 +:1056B0000446012003902068FFF7CCFA18B94FF098 +:1056C00080600FB030BD606C03281BD02068FFF7EE +:1056D000FAFB05460DB12846F3E700212068FFF7E5 +:1056E000BEFA606704212068FFF7B9FAA0670821B5 +:1056F0002068FFF7B4FAE0670C212068FFF7AFFAE3 +:1057000080210851606C032807D003A92068FFF7A7 +:1057100044FC05460DB12846D3E7606C032820D031 +:10572000BDF80C1021655022125B11042068FFF7B0 +:10573000E3FB05460DB12846C3E700212068FFF7CB +:105740008EFA606604212068FFF789FAA0660821B6 +:105750002068FFF784FAE0660C212068FFF77FFAE3 +:10576000206704212068FFF77AFA010DE16404A99B +:105770002046FDF735FD10B14FF08050A1E75020D5 +:10578000005B01040A4600232068FFF77FFB054603 +:105790000DB1284695E7D4E90412A069CDE90012BD +:1057A000029094E80F00FFF760FA002089E70000FC +:1057B000F8B5044600200090002600272068FFF777 +:1057C000FDFA05460DB12846F8BD2068FFF70CFB31 +:1057D000054645B10021A1642068FFF7EFFA0546B0 +:1057E0001DB12846F0E70121A164A06C012808D171 +:1057F00000212068FFF770FA054615B14FF0805080 +:10580000E2E71DE000212068FFF766FA05460DB1CA +:105810002846D9E718492068FFF77AFA054615B1F6 +:105820004FF08050D0E700212068FFF718FA0646B5 +:10583000012080EAD67080F001070098401C00909B +:105840004FF6FF710098884201D2002FDAD04FF650 +:10585000FF710098884202D34FF08070B4E706F0E1 +:105860008040B0F1804F02D10120606401E000204F +:1058700060640020A8E70000000010C170B5044675 +:105880000D4615B94FF0006070BD5022125B110437 +:105890002068FFF766FB06460EB13046F4E70021AC +:1058A0002068FFF7DCF928600020EDE77CB50446AE +:1058B00000200090019000212068FFF7D0F900F04F +:1058C0000070B0F1007F02D14FF400607CBD6946EA +:1058D0002046FFF74AFE05460DB12846F6E7019837 +:1058E00000F4803098B15022125B11042068FFF759 +:1058F000F3F905460DB12846E8E700212068FFF7D7 +:1059000041FA05460DB12846E0E70020DEE74FF0FA +:105910008060DBE77CB50446002000900190002108 +:105920002068FFF79CF900F00070B0F1007F02D111 +:105930004FF400607CBD69462046FFF716FE054621 +:105940000DB12846F6E7019800F4802098B1502266 +:10595000125B11042068FFF7BFF905460DB1284618 +:10596000E8E702212068FFF70DFA05460DB1284649 +:10597000E0E70020DEE74FF08060DBE71FB504467C +:1059800001201649087005F085FA10B3FBF740F8BE +:1059900020B92046FFF75AFD104908700F480078DB +:1059A000012816D00E48006850B90E4B0FCB8DE879 +:1059B0000F000021684605F085FA0949086000BF1C +:1059C0000748006828B90548007840F001000349FD +:1059D00008700248007804B010BD0000D400002018 +:1059E000D80000208C2F0108F0B589B007460D467D +:1059F000144601261648007800F0010010B103207B +:105A000009B0F0BD35B1012D06D0022D0BD0032D0C +:105A100018D10FE0002617E001A8FAF7E3FF079876 +:105A20002060002610E001A8FAF7DCFF089820802B +:105A3000002609E001A8FAF7D5FF0898400A20607F +:105A4000002601E0042600BF00BF3046D8E7000072 +:105A5000D40000202DE9F04786B082460E46174656 +:105A600098464FF0010947F23050FFF703FD002838 +:105A700003DA484606B0BDE8F0874246394630466C +:105A8000FAF7EAFF044614BB47F2305211480168A6 +:105A9000684605F02BFA9DE8070003AB07C303989F +:105AA000102814D10498012811D105F001FA0546F7 +:105AB00005E0FAF7A1FF10B94FF0000906E005F084 +:105AC000F7F9401B47F230518842F2D300BF4846F5 +:105AD000D0E70000D800002010B504462046FFF7AC +:105AE000B5FC10BD2DE9F04387B081460D46164642 +:105AF0001F464FF0010847F23050FFF7BBFC00286B +:105B000003DA404607B0BDE8F0833A4631462846FE +:105B1000FAF7C0FF10BB47F230521148016801A8E4 +:105B200005F0E4F901A807C804AB07C304981028DE +:105B300014D10598022811D105F0BAF9044605E000 +:105B4000FAF75AFF10B94FF0000806E005F0B0F977 +:105B5000001B47F230518842F2D300BF4046D1E7E4 +:105B6000D80000207CB504460D461646164800684D +:105B70001821B0FBF1F01549B0FBF1F04FF47A7148 +:105B8000484301906068B0F5827F0DD12B4600221A +:105B900080212046009600F01BF898B1606D40F01F +:105BA0002000606503207CBD00BF019800B908E0BB +:105BB0000198401E019020688068C0F3C010002842 +:105BC000F3D100BF0020EEE71000002040420F009C +:105BD0002DE9F84F04460D4690461E46DDF8289004 +:105BE000FBF74CFCA0EB0900371AFBF747FC824699 +:105BF0002C480068C0F3CB307843009045E0701C1F +:105C0000002842D0FBF73AFCA0EB0A00B84200D2D1 +:105C1000A7BB2068406820F0E00021684860606809 +:105C2000B0F5827F0DD1A068B0F5004F03D0A06819 +:105C3000B0F5806F05D12068006820F04000216831 +:105C40000860A06AB0F5005F0DD100BF2068006851 +:105C500020F40050216808602068006840F400507B +:105C60002168086000BF012084F8510000BF0020B7 +:105C700084F8500000BF0320BDE8F88FFFE70098CC +:105C800000B900270098401E0090206880682840D6 +:105C9000A84201D1012000E000204045AFD1002002 +:105CA000EAE700001000002030B501460A461378EC +:105CB000521C147843EA042030BDFEF7FBFD00BF00 +:105CC000012005F0DBF8FBE710B500BF502080F3A2 +:105CD0001188BFF34F8FBFF36F8F00BF0CF07EFEB4 +:105CE00018B14FF080500449086000BF002080F3D5 +:105CF000118800BF10BD000004ED00E000B593B0B6 +:105D0000302107A8FAF747FB142102A8FAF743FB52 +:105D100000BF002001902548006840F080502349D2 +:105D200008600846006800F08050019000BF00BF86 +:105D300000BF002001901E48006840F480401C49CC +:105D400008600846006800F48040019000BF00BF72 +:105D5000052007904FF48030089001200990022020 +:105D60000D9041050E9104210F91A821109102215F +:105D700011910721129107A8FCF7BCFD08B1FAF7B1 +:105D8000B9FF0F20029002200390002004904FF4EE +:105D9000A05005904FF480500690052102A8FCF712 +:105DA00047FC08B1FAF7A6FF13B000BD4038024027 +:105DB000007000400348006840F47000014908602A +:105DC0007047000088ED00E010B501200549D1F8CA +:105DD000BC100144034AC2F8BC1000BF0248FDF7E2 +:105DE000DEFF10BD4C2801206807002010B50268B6 +:105DF000294B98420ED0B0F1804F0BD0274B9842E0 +:105E000008D0274B984205D0264B984202D0264B0B +:105E1000984203D122F070024B681A431E4B9842FD +:105E200020D0B0F1804F1DD01C4B98421AD01C4B93 +:105E3000984217D01B4B984214D01B4B984211D05C +:105E40001A4B98420ED01A4B98420BD0194B9842DD +:105E500008D0194B984205D0184B984202D0184BE5 +:105E6000984203D122F44072CB681A4322F0800397 +:105E70004C6943EA040202608B68C3620B68836268 +:105E8000054B984202D0084B984201D10B6903633D +:105E90000123436110BD00000000014000040040E8 +:105EA00000080040000C0040000401400040014098 +:105EB000004401400048014000180040001C004020 +:105EC0000020004070B50546AC6B0020E085E08402 +:105ED0002046FEF73FF870BD70B506460025B46B4E +:105EE00020684069C0F3C01594F83D00212805D111 +:105EF00025B10020E084204600F0C4F82068406905 +:105F0000C0F3801594F83E00222805D125B1002069 +:105F1000E085204600F070F8206C40F0100020640E +:105F20002046FEF717F870BD70B50546AC6B2868C3 +:105F3000006800F48070002842D1E08500BF00BFF7 +:105F400021680C3151E8001F21F4807021680C3168 +:105F500041E80002002AF3D100BF00BF00BF216862 +:105F6000143151E8001F21F001002168143141E88B +:105F70000002002AF3D100BF00BF00BF2168143126 +:105F800051E8001F21F040002168143141E800026F +:105F9000002AF3D100BF202084F83E00206B0128A6 +:105FA0000ED100BF00BF21680C3151E8001F21F065 +:105FB000100021680C3141E80002002AF3D100BF33 +:105FC000206B012804D1A18D2046FDF7C2FF02E01D +:105FD0002046FEF71AFA70BD70B50546AC6B206B13 +:105FE000012805D1A08D41082046FDF7B2FF02E04F +:105FF0002046FEF70BFA70BD00BF00BF02680C32EE +:1060000052E8002F22F4907102680C3242E800132B +:10601000002BF3D100BF00BF00BF0268143252E86A +:10602000002F22F001010268143242E80013002B15 +:10603000F3D100BF016B01290ED100BF00BF026880 +:106040000C3252E8002F22F0100102680C3242E8B4 +:106050000013002BF3D100BF202180F83E10002157 +:106060000163704710B504462068C06820F0400006 +:106070002168C860202084F83D002046FEF730FAF1 +:10608000002010BD00BF00BF02680C3252E8002F94 +:1060900022F0C00102680C3242E80013002BF3D159 +:1060A00000BF202180F83D107047F8B5044694F8F1 +:1060B0003E00222873D1A068B0F5805F0CD1206922 +:1060C00050B90025A66A20684068C0F308003080F7 +:1060D000A06A801CA06215E0A56A0026A068B0F541 +:1060E000805F03D0A06828B9206918B9206840688B +:1060F000287004E02068406800F07F002870A06AE3 +:10610000401CA062E08D401E80B2E085002844D192 +:106110002068C06820F020002168C8602068C0683E +:1061200020F480702168C8602068406920F0010078 +:1061300021684861202084F83E00206B012826D188 +:106140000020206300BF00BF21680C3151E8001F10 +:1061500021F0100021680C3141E80002002AF3D13F +:1061600000BF2068006800F0100010280AD100BFAE +:10617000002000902068006800902068406800902F +:1061800000BF00BFA18D2046FDF7E3FE02E02046E0 +:10619000FEF73BF90020F8BD01E00020FBE70220FC +:1061A000F9E700002DE9F84F04462068006920F463 +:1061B0004050E1680843216808612169A0680843EC +:1061C00061690843E169084300902068C06849F2AA +:1061D0000C618843009908432168C86020684069C1 +:1061E00020F44070A169084321684861764920681D +:1061F000884203D075492068884203D1FCF712FB1E +:10620000814602E0FCF7FEFA8146E069B0F5004FF6 +:106210006CD102206168A0FB015003461920A9FB44 +:10622000007001462A463846FAF72CF86421B0FB84 +:10623000F1F04FEA001A02206168A0FB01510B4601 +:106240001920A9FB00712A463846FAF71BF8834645 +:1062500002206168A0FB015003461920A9FB0071D0 +:106260002A463846FAF70EF86421B0FBF1F000EB4D +:10627000C00101EB0010ABEB8000322101EBC0004C +:106280006421B0FBF1F000F0F8000AEB400A0220B4 +:106290006168A0FB015003461920A9FB007001466C +:1062A0002A463846F9F7EEFF834602206168A0FBD4 +:1062B000015003461920A9FB00712A463846F9F718 +:1062C000E1FF6421B0FBF1F000EBC00101EB001035 +:1062D000ABEB8000322101EBC0006421B0FBF1F098 +:1062E00000F007005044216888606AE0042061687B +:1062F000A0FB015003461920A9FB007001462A4665 +:106300003846F9F7BFFF824604206168A0FB0150C0 +:1063100003461920A9FB007001462A463846F9F7C2 +:10632000B1FF6421B0FBF1F000EBC00101EB001004 +:10633000AAEB8000322101EB00106421B0FBF1F0E8 +:1063400000F0F00A04206168A0FB017003461920E8 +:10635000A9FB00513A462846F9F794FF6421B0FBA7 +:10636000F1F00AEB001A04206168A0FB01510B4612 +:106370001920A9FB00712A463846F9F783FF8346A6 +:1063800004206168A0FB015003461920A9FB00709E +:1063900001462A463846F9F775FF6421B0FBF1F053 +:1063A00000EBC00101EB0010ABEB8000322101EBF0 +:1063B00000106421B0FBF1F000F00F0050442168A0 +:1063C0008860BDE8F88F0000001001400014014013 +:1063D00077B581B0044615460298A062A5850020D5 +:1063E0002064222084F83E002A48A16BC8632A4812 +:1063F000A16B08642948A16BC8640020A16B0865E3 +:1064000002AE32682368191D2B46A06BFAF7C6FE50 +:1064100000BF00200090206800680090206840685D +:10642000009000BF00BF00BF002084F83C0000BF08 +:10643000206970B100BF00BF21680C3151E8001F16 +:1064400041F4807021680C3141E80002002AF3D148 +:1064500000BF00BF00BF2168143151E8001F41F0A8 +:1064600001002168143141E80002002AF3D100BF85 +:1064700000BF00BF2168143151E8001F41F0400007 +:106480002168143141E80002002AF3D100BF002046 +:1064900004B070BD295F0008D95F0008D95E00080C +:1064A000014691F83D00212828D18868B0F5805F29 +:1064B0000BD1086948B90A6A1088C0F308000B6854 +:1064C0005860086A801C086205E00B6A581C086264 +:1064D00018780B685860C88C401E80B2C88458B9C0 +:1064E0000868C06820F080000B68D8600868C06841 +:1064F00040F040000B68D860002070470220FCE7A5 +:106500002DE9F04104460D4617469846069E34E0B4 +:10651000701C88B32EB1FAF7B1FFA0EB0800B042AF +:106520002BD900BF00BF21680C3151E8001F21F4B6 +:10653000D07021680C3141E80002002AF3D100BF7D +:1065400000BF00BF2168143151E8001F21F0010095 +:106550002168143141E80002002AF3D100BF202055 +:1065600084F83D0084F83E0000BF002084F83C0021 +:1065700000BF0320BDE8F081FFE7206800682840E5 +:10658000A84201D1012000E00020B842C0D0002084 +:10659000F0E7000008B50D480068006800F0100042 +:1065A00010280ED100BF0020009008480068006845 +:1065B0000090064800684068009000BF00BF0AF0E5 +:1065C000F3FE0248FDF7C8FC08BD00006406002089 +:1065D0002DE9F04104460D46D4F8C87204F5307038 +:1065E000D4F8D41250F8210010B90320BDE8F0818E +:1065F00004F53070D4F8D41250F8216005F00F0083 +:1066000000EB800104F1140000EB8100406838B316 +:1066100005F00F0000EB800104F1140000EB810095 +:10662000416805F00F0000EBC00207F13C0000EBF1 +:106630008200C068B1FBF0F200FB121080B90021AB +:1066400005F00F0000EB800204F1140000EB820063 +:10665000416000231A462946204601F02CF917E034 +:106660000020C6F8140204F53170D4F8D41250F8A2 +:106670002100006960B1D6F8080204F53171D4F840 +:10668000D42251F822102A460B6906F50471984766 +:106690000020ABE770B504460E4604F53070D4F820 +:1066A000D41250F82150D4F8D41250F8210008B96F +:1066B000032070BD3146204600F059FFC5F80C029A +:1066C000D5F8040204F53171D4F8D43251F823100E +:1066D000CA6805F5037190470020EAE770B50446E3 +:1066E0000D4630480178204600F013FE00212D4869 +:1066F000007800F00F0000EB800204F1140000EBC2 +:106700008200018228480178204600F002FE002124 +:106710002548007800F00F0000EB800204F5AA7015 +:1067200000EB8200018221480178204600F0F1FD53 +:1067300000211E48007800F00F0000EB800204F1F9 +:10674000140000EB820001821848007800F00F006E +:1067500000EB800204F1140000EB8200418204F59A +:106760003070D4F8D41250F82100C8B104F531715A +:10677000D4F8D42251F822104868804704F53071CB +:10678000D4F8D42251F8220001F0BEFB002104F518 +:106790003070D4F8D42240F822100020C4F8BC0293 +:1067A000002070BDD3010020D4010020D5010020BD +:1067B00070B5044604F53070D4F8D41250F8215066 +:1067C0000DB9032070BD04F53170D4F8D41250F81F +:1067D000210098B195F80002FF280FD095F801220A +:1067E00095F8000204F53171D4F8D46251F82610FE +:1067F0008B6829469847FF2085F800020020E1E7D2 +:1068000001460A2008800148704700004C01002022 +:106810002DE9F041044682210D4800F0A0FC054618 +:1068200001210B4800F09BFC06468121084800F03E +:1068300096FC07460DB11020A8710EB14020B08023 +:106840000FB14020B880432020800148BDE8F0818E +:10685000900100202DE9F041044682210E4800F00D +:106860007EFC054601210C4800F079FC064681219A +:10687000094800F074FC07460DB11020A87116B14C +:106880004FF40070B08017B14FF40070B88043200F +:1068900020800148BDE8F081900100202DE9F04101 +:1068A000044682210D4800F05AFC054601210B48A0 +:1068B00000F055FC06468121084800F050FC0746D0 +:1068C0000DB11020A8710EB14020B0800FB1402052 +:1068D000B880432020800148BDE8F081900100206D +:1068E00070B504460E464FF4077001F00FFB0546E5 +:1068F00045B9002104F53070D4F8D42240F82210B4 +:10690000022070BD4FF407712846F9F744FD04F5E5 +:106910003070D4F8D41240F82150D4F8D41250F882 +:106920002100C4F8BC02207C98BB4FF40073022203 +:1069300050480178204600F0BBFE01214D48007808 +:1069400000F00F0000EB800204F1140000EB820065 +:1069500001824B02022248480178204600F0A8FE3E +:1069600001214548007800F00F0000EB800204F59B +:10697000AA7000EB8200018210214048007800F0EC +:106980000F0000EB800204F1140000EB8200418252 +:1069900032E0FFE74023022236480178204600F02B +:1069A00087FE01213348007800F00F0000EB8002E1 +:1069B00004F1140000EB82000182402302222E48E1 +:1069C0000178204600F074FE01212B48007800F089 +:1069D0000F0000EB800204F5AA7000EB8200018238 +:1069E00010212648007800F00F0000EB800204F12F +:1069F000140000EB82004182082303221F48017823 +:106A0000204600F055FE01211C48007800F00F00E0 +:106A100000EB800204F1140000EB820001820020F0 +:106A2000C5F8040204F53171D4F8D42251F82210CB +:106A3000086880470020C5F81402C5F81802D5F888 +:106A4000040208B902205CE7207C48B94FF40073C7 +:106A5000094801782046D5F8042200F041FE07E0FD +:106A60004023054801782046D5F8042200F038FE7E +:106A7000002046E7D3010020D4010020D5010020EA +:106A800070B5044604F53070D4F8D41250F8215093 +:106A9000D4F8D41250F8210008B9032070BD207C2E +:106AA00048B94FF40073094801782046D5F804220C +:106AB00000F016FE07E04023044801782046D5F890 +:106AC000042200F00DFE0020E8E70000D4010020C1 +:106AD000024609B90320704702F53170D2F8D4326A +:106AE00040F823100020F6E710B5024602F530709A +:106AF000D2F8D44250F824300BB9032010BDC3F8AB +:106B000004120020FAE730B503460C4603F5307056 +:106B1000D3F8D45250F8251009B9032030BDC1F87C +:106B20000842C1F810220020F8E72DE9FC41054693 +:106B30000C4605F53070D5F8D41250F821600020CD +:106B400001900090804616B90320BDE8FC812078B2 +:106B500000F0600000283DD020287CD1E08868B398 +:106B6000207800F08000B8B1E288607805F53171D6 +:106B7000D5F8D4C251F82C108B6831469847E0887C +:106B8000072801D9072000E0E08807463A46314649 +:106B9000284600F015F91CE0607886F80002E088CD +:106BA000402801D2E08800E0402086F8010296F8F3 +:106BB00001223146284600F0E2F80AE0607805F547 +:106BC0003171D5F8D42251F8221000228B68214669 +:106BD000984747E0607830B1012832D00A2813D0B6 +:106BE0000B282FD121E095F89C02032805D1022221 +:106BF0006946284600F0E4F805E02146284600F002 +:106C0000B2F84FF0030824E095F89C02032805D160 +:106C1000012201A9284600F0D3F805E021462846C4 +:106C200000F0A1F84FF0030813E095F89C02032848 +:106C300005D02146284600F096F84FF0030808E0FA +:106C400009E006E02146284600F08DF84FF00308E1 +:106C500000BF00BF06E02146284600F084F84FF050 +:106C6000030800BF00BF40466FE7000070B5044650 +:106C700004F53070D4F8D41250F821500126D4F81D +:106C8000D41250F8210008B9032070BDD5F81402C1 +:106C9000C8B90120C5F814020C48007800F00F00B4 +:106CA00000EB800204F1140000EB8200D5F8101212 +:106CB0004160064801782046D5F81032D5F8082200 +:106CC00000F0F9FD00263046DFE70000D301002088 +:106CD00070B504460D460026D4F8B802294642682D +:106CE0002046904700B10326304670BD70B504467B +:106CF0000D4694F89C02012804D0022803D00328F2 +:106D00000CD101E000BF00BF6888012805D1002038 +:106D1000C4F8A402204600F064F804E029462046A6 +:106D200000F021F800BF00BF70BD02460020704790 +:106D300002460020704770B506460C4615462B46A5 +:106D400022460021304600F0CBFC002070BD70B51B +:106D500006460C4615462B4622460021304600F0DA +:106D6000AAFD002070BD70B504460D468021204666 +:106D700000F075FD0021204600F071FD70BD70B57A +:106D800004460E4615460320C4F894024FF4AC7036 +:106D90000551001D05512B4632460021204600F0CA +:106DA0009FFC002070BD10B504460520C4F8940275 +:106DB00000231A461946204600F092FC002010BD20 +:106DC00070B504460E4615460220C4F89402A5612B +:106DD000E5612B4632460021204600F06CFD002084 +:106DE00070BD10B504460420C4F8940200231A466E +:106DF0001946204600F05FFD002010BD70B5054625 +:106E00000C462DB92246064906A000F012FA04E00D +:106E10002246034903A000F00CFA014870BD0000AF +:106E20000C0B012043444320436F6E6669670000EA +:106E3000024612200880014870470000000100202F +:106E400070B505460C462DB92246064906A000F04D +:106E5000F0F904E02246034903A000F0EAF90148F2 +:106E600070BD00000C0B012043444320496E746543 +:106E700072666163650000000246042008800148D4 +:106E8000704700001401002070B505460C462246EC +:106E9000024903A000F0CDF9004870BD0C0B0120A1 +:106EA00053544D6963726F656C656374726F6E697C +:106EB0006373000070B505460C462DB9224606499D +:106EC00006A000F0B6F904E02246034903A000F052 +:106ED000B0F9014870BD00000C0B012053544D3334 +:106EE00032205669727475616C20436F6D506F72F9 +:106EF0007400000070B505460C461A202080F9F792 +:106F00002FFF014870BD00001801002070B5044635 +:106F10000D46E888012804D029462046FFF723FFC4 +:106F20001EE094F89C02012804D0022803D0032814 +:106F300010D109E000BF0020A060012204F1080187 +:106F40002046FFF73DFF0AE00122211D2046FFF702 +:106F500037FF04E029462046FFF705FF00BF00BFCA +:106F600070BDF8B504460E460020009000270025AD +:106F700070880012082875D2DFE800F0C7040C20E2 +:106F8000C7C7A5B5207CD4F8B4120A6869469047F3 +:106F90000746C1E0207C40B9D4F8B802816A68464F +:106FA000884707460220787007E0D4F8B802C16A23 +:106FB00068468847074602207870ADE0B07806281A +:106FC00078D2DFE800F00316293C5063D4F8B4020D +:106FD000406838B1207CD4F8B4124A6869469047BA +:106FE000074605E031462046FFF7BDFE681CC5B2E6 +:106FF00067E0D4F8B402806838B1207CD4F8B412C9 +:107000008A6869469047074605E031462046FFF703 +:10701000AAFE681CC5B254E0D4F8B402C06838B106 +:10702000207CD4F8B412CA6869469047074605E048 +:1070300031462046FFF797FE681CC5B241E0D4F800 +:10704000B402006938B1207CD4F8B4120A696946E8 +:107050009047074605E031462046FFF784FE681C4E +:10706000C5B22EE051E0D4F8B402406938B1207CBA +:10707000D4F8B4124A6969469047074605E031469C +:107080002046FFF770FE681CC5B21AE0D4F8B402BF +:10709000806940B1207CD4F8B4128A69694690476F +:1070A000074606E006E031462046FFF75CFE681C16 +:1070B000C5B206E031462046FFF755FE681CC5B252 +:1070C00000BF00BF28E0207C30B9D4F8B802416B83 +:1070D00068468847074605E031462046FFF743FEED +:1070E000681CC5B218E0207C40B9D4F8B802016B26 +:1070F0006846884707460720787005E031462046F5 +:10710000FFF731FE681CC5B206E031462046FFF7A6 +:107110002AFE681CC5B200BF00BF05B1F8BDF088EB +:10712000C0B1BDF8000080B1F088BDF80010884201 +:1071300002DDBDF8000000E0F0880090BDF80020FE +:1071400039462046FFF73CFE07E031462046FFF770 +:107150000AFE02E02046FFF744FE00BFDEE72DE90D +:10716000F84105460F462C462E464FF00008708821 +:107170003178884218DD307800900FE0694620466B +:1071800000F020F804466078052807D1A04698F85A +:107190000200B84200D106E04FF000087088BDF848 +:1071A00000108842EADC00BF4046BDE8F881014695 +:1071B00000200A4602E0431CD8B2521C1378002B70 +:1071C000F9D1704710B5024610460B880478234465 +:1071D0000B800378981810BD70B504460D4694F8DE +:1071E0009C02012804D0022803D003281AD101E010 +:1071F00000BF00BFE888022804D029462046FFF7D8 +:10720000B2FD14E00120E060D4F8A40218B1E068F7 +:1072100040F00200E060022204F10C012046FFF77A +:10722000CFFD04E029462046FFF79DFD00BF00BFCB +:1072300070BD2DE9F04107460D46904600240FB978 +:10724000BDE8F0813E463046FFF7B1FF022101EB79 +:107250004000A8F8000098F800002855601CC4B24F +:1072600003202855601CC4B208E030782855761CED +:10727000601CC4B200202855601CC4B230780028BD +:10728000F3D100BFDCE70146002031B1012906D06F +:10729000022906D0032908D105E0002007E00320D9 +:1072A00005E0012003E0032001E0032000BF00BF50 +:1072B00070472DE9F04104460D46164614B90320E7 +:1072C000BDE8F0810020C4F8B802C4F8C402C4F8D4 +:1072D000D0020DB1C4F8B452012084F89C0226708B +:1072E000204600F04DF907463846E9E72DE9F04120 +:1072F00004460D46002600272946D4F8C802FAF7AE +:1073000084FA06463046FFF7BEFF07463846BDE81A +:10731000F0812DE9F04104460D460026002729465C +:10732000D4F8C802FAF73CFA06463046FFF7ABFF3E +:1073300007463846BDE8F0812DE9F04704460F4680 +:107340009146002F56D104F11405D4F89402022876 +:1073500046D1D5E9020188420FD9D5E90201401A88 +:10736000A86049462046AA68FFF7F1FC00231A46A8 +:107370001946204600F0B4F932E0D5E902108842FF +:1073800017D1E9686868884213D36868D4F89812FE +:1073900088420ED2002211462046FFF7D8FC00207A +:1073A000C4F8980200231A461946204600F098F9BE +:1073B00016E094F89C0203280BD1D4F8B802C068F8 +:1073C00038B10020C4F8D402D4F8B802C16820460D +:1073D00088478021204600F042FA2046FFF7E3FC70 +:1073E00094F8A00250B3204600F0BCFA002084F8C4 +:1073F000A00223E047F080012046FFF796FC0646F6 +:10740000FF2E1BD0D6B994F89C02032816D104F5A0 +:107410002E7050F82600406980B1C4F8D46204F59B +:107420002E7050F826003946426920469047804623 +:10743000B8F1000F02D04046BDE8F0870020FBE71E +:107440002DE9F04705460F4690464FF00009002F02 +:1074500051D105F5AA76D5F8940203286FD1D6E963 +:107460000201884210D9D6E90201401AB060D6E97B +:107470000201884201D2B06800E0F068024641464D +:107480002846FFF758FC5AE095F8AA0200F01F00C2 +:1074900020B1012804D0022812D109E0002411E013 +:1074A00040F2AE20415D2846FFF742FC044609E069 +:1074B00040F2AE20415D2846FFF737FC044601E06C +:1074C000002400BF00BF94B995F89C0203280ED198 +:1074D00005F52E7050F82400006940B1C5F8D4427B +:1074E00005F52E7050F82400016928468847284683 +:1074F000FFF777FC23E007F07F012846FFF715FC34 +:107500000446FF2C1BD0D4B995F89C02032810D157 +:1075100005F52E7050F82400806950B1C5F8D442AA +:1075200005F52E7050F824003946826928469047A8 +:107530008146B9F1000F02D04846BDE8F08700202F +:10754000FBE701460020704770B504460025012086 +:1075500084F89C02D4F8B80238B12179D4F8B80282 +:1075600042682046904700B10325284670BD70B59B +:1075700004460D462946D4F8C802FAF784F970BDCE +:1075800010B50446207800282AD11648C0F80845CE +:10759000C4F8C8024FF0A0401249086004204860B7 +:1075A00002211048C1600021016102218161002196 +:1075B000C16101624162C1620163FAF7CAFD08B1AB +:1075C000F9F798FB80210748FAF76FF8402200216D +:1075D0000448FAF76FF8802201210248FAF76AF8A6 +:1075E000002010BD0C1D012010B50246D2F8C83293 +:1075F00001F08000802809D101F07F0000EBC00479 +:1076000003F13C0000EB8400807810BD01F07F00A6 +:1076100000EBC00403F51F7000EB84008078F4E7F2 +:1076200070B504460D4604F52E70D4F8D41250F807 +:10763000210008B9032070BD94F89C02032811D1E1 +:1076400004F52E70D4F8D41250F82100006A48B125 +:1076500004F52E70D4F8D41250F821002946026A9D +:10766000204690470020E6E770B504460D4604F535 +:107670002E70D4F8D41250F8210008B9032070BD40 +:1076800094F89C02032811D104F52E70D4F8D4127A +:1076900050F82100406A48B104F52E70D4F8D41295 +:1076A00050F821002946426A204690470020E6E72C +:1076B0002DE9F04704460F4615461E464FF00008D8 +:1076C000C1462B4632463946D4F8C802FAF7E6F8E6 +:1076D00080464046FFF7D7FD81464846BDE8F08723 +:1076E0002DE9F04704460D4616461F464FF00008A8 +:1076F000C1463B4632462946D4F8C802FAF714F987 +:1077000080464046FFF7BFFD81464846BDE8F0870A +:1077100070B504460025012084F89C020020C4F8BE +:1077200094026060C4F8A40284F8A002D4F8B802FD +:1077300058B1D4F8B802406838B12179D4F8B80209 +:1077400042682046904700B103254023002211469D +:107750002046FFF7ADFF01214FF4B27001534021E5 +:10776000001F01514023002280212046FFF7A0FF87 +:107770000121A18440212162284670BD014691F873 +:107780009C02042803D191F89D0281F89C020020FC +:10779000704710B5044694F89C0203280BD1D4F826 +:1077A000B80240B1D4F8B802C06920B1D4F8B80228 +:1077B000C16920468847002010BD02461174002090 +:1077C00070472DE9F04104460D4600260027294662 +:1077D000D4F8C802FAF7EAFD06463046FFF753FD33 +:1077E00007463846BDE8F08170B504460D46294687 +:1077F00004F2AA2000F077F80120C4F894024FF4B4 +:107800002C70005BC4F8980294F8AA0200F01F00E4 +:1078100020B1012809D0022815D10DE004F2AA21D7 +:10782000204600F083F9064616E004F2AA2120461D +:1078300000F013FB06460FE004F2AA21204600F0F8 +:10784000CCF9064608E094F8AA0200F08001204630 +:1078500000F005F8064600BF00BF304670BD2DE9B8 +:10786000F04104460D46002600272946D4F8C802F8 +:10787000FAF786F806463046FFF705FD0746384614 +:10788000BDE8F08170B5044600250026D4F8C80292 +:10789000FAF7B0FD05462846FFF7F5FC06463046E8 +:1078A00070BD014691F89C0281F89D02042081F888 +:1078B0009C02002070472DE9F04704460D4616460D +:1078C0001F464FF00008C1463B4632462946D4F8D1 +:1078D000C802FAF79AF880464046FFF7D4FC814682 +:1078E0004846BDE8F08770B505460E463446207818 +:1078F0002870641C20786870641C2046FEF7D4F958 +:107900006880641C641C2046FEF7CEF9A880641CC5 +:10791000641C2046FEF7C8F9E88070BD38B50446FF +:107920000D46002000900DB9032038BDC4F8B852B0 +:1079300004F52E70D4F8D41250F82100C06A50B16A +:1079400004F52E70D4F8D42250F82200C16A68469B +:107950008847C4F8D002D4F8D802401CC4F8D80232 +:107960000020E2E701460020704770B504460D464E +:10797000A88810BBE88800BB688880281DD2A8783A +:1079800000F07F0694F89C02032804D12946204683 +:10799000FFF7E9F915E084F89E6231462046FFF7CB +:1079A00010FF2046FFF71DFA1EB1022084F89C024A +:1079B00007E0012084F89C0203E029462046FFF7F7 +:1079C000D2F970BD70B504460D460026D4F8B80251 +:1079D00030B1D4F8B80229460268204690470646DE +:1079E000304670BD70B504460E460025B0783D495E +:1079F000087008460078012805D931462046FFF76F +:107A0000B2F9032070BD94F89C02022802D003282A +:107A100059D11FE033480078C0B132480078606027 +:107A2000304801782046FFF7CDFF05463DB131468D +:107A30002046FFF798F9022084F89C0209E02046CE +:107A4000FFF7CFF9032084F89C0202E02046FFF7FD +:107A5000C8F943E02348007870B9022084F89C02FA +:107A60002048007860601F4801782046FFF730F911 +:107A70002046FFF7B6F925E01A4909786068884280 +:107A80001DD021792046FFF723F916480078606061 +:107A9000144801782046FFF795FF05465DB1314651 +:107AA0002046FFF760F921792046FFF711F90220FF +:107AB00084F89C0206E02046FFF793F902E0204696 +:107AC000FFF78FF90AE031462046FFF74CF90548E9 +:107AD00001782046FFF7FCF8032500BF00BF2846C9 +:107AE00090E700004801002070B505460C4660880C +:107AF000012805D1C5F8A4022846FFF772F90EE067 +:107B00006088022807D1A088001285F8A0022846C4 +:107B1000FFF767F903E021462846FFF724F970BD17 +:107B200010B504462046FFF7ADFE10BD70B5044603 +:107B30000D460026287800F0600088B1202802D089 +:107B4000402842D100E000BF04F52E70D4F8D412D2 +:107B500050F821002946826820469047064639E0C1 +:107B600068780A282AD2DFE800F01A24291F290A97 +:107B70000529150F29462046FFF7F3F923E029468A +:107B80002046FFF7F2FE1EE029462046FFF72AFFB7 +:107B9000064618E029462046FFF7B8F913E02946C3 +:107BA0002046FFF719FB0EE029462046FFF79CFF11 +:107BB00009E029462046FFF799F804E029462046C7 +:107BC000FFF7D1F800BF00BF04E029462046FFF7C9 +:107BD000CAF800BF00BF304670BD2DE9F04705462A +:107BE0000F464FF000093C79387800F06000F8B19A +:107BF000202802D040287DD100E000BF2146284641 +:107C0000FFF793F80646FF2E11D086B9C5F8D46267 +:107C100005F52E7050F82600806840B105F52E70ED +:107C200050F826003946826828469047814610E180 +:107C3000787800287AD001282FD003286ED195F8C3 +:107C40009C02022802D0032820D110E054B1802CDD +:107C500008D021462846FFF702FE80212846FFF77C +:107C6000FEFD03E039462846FFF77DF813E07888EB +:107C700040B93CB1802C05D0F88818B92146284677 +:107C8000FFF7EDFD2846FFF7ACF804E0394628463B +:107C9000FFF769F800BF00BFD4E095F89C02022806 +:107CA00002D003283BD110E054B1802C08D02146EB +:107CB0002846FFF7D4FD80212846FFF7D0FD03E0DA +:107CC00039462846FFF74FF82EE0788820BB04F0AD +:107CD0007F0018B121462846FFF708FB2846FFF72A +:107CE00080F821462846FFF720F80646FF2E13D0DD +:107CF00096B900E0A8E0C5F8D46205F52E7050F8FA +:107D00002600806840B105F52E7050F826003946EF +:107D1000826828469047814606E007E08DE03946B4 +:107D20002846FFF720F800BF00BF8BE095F89C02C3 +:107D3000022802D0032879D126E034B1802C04D067 +:107D400039462846FFF70FF875E004F080008028D8 +:107D500008D104F07F0000EB800105F1140000EB76 +:107D6000810007E004F07F0000EB800105F5AA70B8 +:107D700000EB810080460020C8F800000222414646 +:107D80002846FFF71DF856E004F0800080280ED149 +:107D900004F00F0000EB800105F1140000EB8100FE +:107DA000008A98B939462846FEF7DDFF43E004F023 +:107DB0000F0000EB800105F5AA7000EB8100008A3E +:107DC00020B939462846FEF7CEFF34E004F08000A3 +:107DD000802808D104F07F0000EB800105F1140039 +:107DE00000EB810007E004F07F0000EB800105F567 +:107DF000AA7000EB810080460CB1802C03D10020DA +:107E0000C8F800000CE021462846FFF7EDFB20B142 +:107E10000120C8F8000003E008E00020C8F80000D6 +:107E2000022241462846FEF7CBFF04E039462846A9 +:107E3000FEF799FF00BF00BF04E039462846FEF771 +:107E400092FF00BF00BF04E039462846FEF78BFFD3 +:107E500000BF00BF4846BDE8F0872DE9F041054668 +:107E60000E460027307800F0600030B1202802D0A4 +:107E7000402840D100E000BF00BF95F89C020128D7 +:107E800004D0022803D003282ED101E000BF00BF98 +:107E90003079012823D831792846FEF749FF044676 +:107EA000FF2C14D09CB905F52E7050F82400806882 +:107EB00058B1C5F8D44205F52E7050F8240031466B +:107EC000826828469047074602E0032700E0032720 +:107ED000F08840B93FB92846FEF783FF03E03146FA +:107EE0002846FEF740FF04E031462846FEF73BFFF8 +:107EF00000BF00BF04E031462846FEF734FF00BF54 +:107F000000BF3846BDE8F0817047000001460148D7 +:107F1000704700001822012070B504460B46224627 +:107F20001978587801282CD140F61C0080581D780B +:107F300005F00F060125B540ADB2284340F61C05FB +:107F4000A85002F5106000EB4110006800F40040FA +:107F5000F0BB9889C0F30A001D7940EA854040EAE9 +:107F6000815040F0805040F4004002F5106505EB70 +:107F700041152D68284302F5106505EB4115286071 +:107F80002DE040F61C0080581D7805F00F060125F5 +:107F9000B540144E06EA0545284340F61C05A85096 +:107FA00002F5306000EB4110006800F4004078B941 +:107FB0009889C0F30A001D7940EA854040F080505E +:107FC00040F4004002F5306505EB41152D6800E0F6 +:107FD00005E0284302F5306505EB411528600020D7 +:107FE00070BD00000000FFFF01460A464FF410601C +:107FF0008058C30ADB024FF41060835040F604003F +:10800000805840F4807340F604008350002070478D +:108010000FB470B504460A98012817D1A06B20F45C +:108020008030A063E0681A490840E060E06820F40E +:108030004010E0601198012803D1E06840F48010FE +:10804000E060204600F026F8054612E0E06840F0C7 +:108050004000E060204600F01DF805460E9820B96B +:10806000A06B40F48030A06303E0A06B20F480306C +:10807000A0630898012807D1A06840F00600A0601E +:10808000A06840F02000A060284670BC5DF814FB9A +:10809000BFFFBDFF08B501460020009000BF00985B +:1080A000401C0090104A0098904201D9032008BD5E +:1080B000086900F000400028F1D000200090086915 +:1080C00040F00100086100BF0098401C0090064A83 +:1080D0000098904201D90320E9E7086900F0010007 +:1080E0000028F1D100BFE2E7400D030070B504465F +:1080F0000B46224619785878012848D102F51060BD +:1081000000EB4110006800F00040B0F1004F17D1C3 +:1081100002F5106000EB4110006840F0006502F5C8 +:10812000106000EB4110056002F5106000EB41109B +:10813000006840F0804502F5106000EB41100560DA +:1081400040F63C0080581D7805F00F060125B5402B +:10815000ADB2A84340F63C05A85040F61C0080583C +:108160001D7805F00F060125B540ADB2A84340F6D5 +:108170001C05A85002F5106000EB411000682B4D63 +:10818000284002F5106505EB411528604BE002F52B +:10819000306000EB4110006800F00040B0F1004F8B +:1081A00017D102F5306000EB4110006840F0006527 +:1081B00002F5306000EB4110056002F5306000EB25 +:1081C0004110006840F0804502F5306000EB41103E +:1081D000056040F63C0080581D7805F00F0601252B +:1081E000B540134E06EA0545A84340F63C05A850A5 +:1081F00040F61C008558187800F00F060120B040AA +:108200000B4E06EA0040854340F61C00855002F5FF +:10821000306000EB41100068064D284002F53065E3 +:1082200005EB41152860002070BD0000007833EC9C +:108230000000FFFF0078F3EF01460A46D2F8000E77 +:1082400020F00300C2F8000E40F60400805820F031 +:10825000020340F6040083500020704701460A469E +:10826000D2F8000E20F00300C2F8000E40F6040021 +:10827000805840F0020340F604008350002070470D +:108280000FB4F0B5054600272E46002405E0002176 +:1082900005F5827040F82410641C0F2CF7D3109859 +:1082A000A0B940F60400805940F0020140F60400F5 +:1082B0008151A86B40F40010A863A86B20F4002043 +:1082C000A863A86B20F48020A86307E0A86B20F4C3 +:1082D0000010A863A86B40F40020A8630020C6F833 +:1082E000000ED6F80008C6F800080B9801280BD13C +:1082F000089820B90021284600F0BCFD08E00121C3 +:10830000284600F0B7FD03E00321284600F0B2FD47 +:108310001021284600F0B2FC00B10127284600F0E9 +:1083200083FC00B1012700214FF401608151001D41 +:10833000815140F61C00815100242EE006F51060AA +:1083400000EB4410006800F00040B0F1004F10D185 +:108350003CB94FF0006106F5106000EB441001607D +:108360000DE04FF0904106F5106000EB4410016005 +:1083700005E0002106F5106000EB441001600021CB +:1083800006F5106000EB441001614FF67F3106F5F1 +:10839000106000EB44108160641C0698A042CDD8A8 +:1083A00000242EE006F5306000EB4410006800F079 +:1083B0000040B0F1004F10D13CB94FF0006106F51C +:1083C000306000EB441001600DE04FF0904106F585 +:1083D000306000EB4410016005E0002106F53060DC +:1083E00000EB44100160002106F5306000EB441002 +:1083F00001614FF67F3106F5306000EB441081607B +:10840000641C0698A042CDD84FF40160805920F436 +:1084100080714FF4016081510020A8616FF08040AD +:108420006861099818B9A86940F01000A861A869A6 +:1084300009490843A8610C9818B1A86940F00800E0 +:10844000A8611098012803D1A86904490843A861CC +:108450003846F0BC5DF814FB00383C800400004056 +:108460000146886820F00100886000207047000005 +:10847000F0B505460B4614462A4619785878012867 +:1084800075D1986920BB02F5106000EB41100069BE +:108490006D4E304002F5106606EB4116306102F574 +:1084A000106000EB4110006940F4002602F51060F6 +:1084B00000EB4110066102F5106000EB411000690D +:1084C000C60CF60402F5106000EB4110066137E0BF +:1084D00002F5106000EB41100069C60CF60402F5CD +:1084E000106000EB4110066102F5106000EB4110D6 +:1084F0000069554E304002F5106606EB41163061BA +:10850000DE689869B04201D9D868986102F51060B8 +:1085100000EB4110006940F4002602F5106000EB0A +:108520004110066102F5106000EB411000699E6980 +:10853000C6F31206304302F5106606EB41163061B1 +:10854000012C15D1586928B102F5106000EB4110DB +:108550005E69466102F5106000EB4110006840F072 +:10856000044602F5106000EB411006606AE01BE073 +:1085700002F5106000EB4110006840F0044602F57F +:10858000106000EB41100660986900285AD040F650 +:10859000340080581E7806F00F070126BE40304395 +:1085A00040F63406B0504DE002F5306000EB41106B +:1085B0000069C60CF60402F5306000EB411006615C +:1085C00002F5306000EB411000691F4E304002F5AB +:1085D000306606EB41163061986908B1D868986139 +:1085E000D868D86102F5306000EB4110006940F4B2 +:1085F000002602F5306000EB4110066102F53060A4 +:1086000000EB41100069DE69C6F31206304302F543 +:10861000306606EB41163061012C07D1186928B18C +:1086200002F5306000EB41101E69466102F53060D2 +:1086300000EB4110006840F0044602F5306000EBAA +:10864000411006600020F0BDFFFF07E070B5034653 +:108650000C4619461D6C1848854209D94FF4306004 +:10866000405800F00040B0F1004F01D1002070BD33 +:108670000026C1F8106BD1F8100B40F40026C1F8A9 +:10868000106BD1F8100B40F01806C1F8106BD1F840 +:10869000100B40F0C046C1F8106B012C09D1C1F895 +:1086A000142B4FF43060405840F080264FF4306077 +:1086B00046500020DBE700000A30544F30B5044636 +:1086C0000B4622461978587801281ED102F5106011 +:1086D00000EB4110006820F4001502F5106000EB7B +:1086E000411005601879032802D0187902282AD190 +:1086F00002F5106000EB4110006840F0805502F573 +:10870000106000EB411005601DE002F5306000EBE9 +:108710004110006820F4001502F5306000EB4110B4 +:1087200005601879032802D0187902280BD102F5C8 +:10873000306000EB4110006840F0805502F5306079 +:1087400000EB41100560002030BD30B504460B46FB +:10875000224619785878012821D102F5106000EBE3 +:108760004110006800F0004060B959B102F5106096 +:1087700000EB4110006820F0804502F5106000EB2E +:108780004110056002F5106000EB4110006840F4F4 +:10879000001502F5106000EB4110056020E002F5C5 +:1087A000306000EB4110006800F0004060B959B142 +:1087B00002F5306000EB4110006820F0804502F5C2 +:1087C000306000EB4110056002F5306000EB4110B5 +:1087D000006840F4001502F5306000EB41100560C0 +:1087E000002030BD2DE9F84381460E4617464D4620 +:1087F0003478707801287DD1B06920BB05F5106010 +:1088000000EB44100069C849084005F5106101EB10 +:108810004411086105F5106000EB4410006940F454 +:10882000002105F5106000EB4410016105F51060B2 +:1088300000EB44100069C10CC90405F5106000EBA1 +:108840004410016155E005F5106000EB441000692B +:10885000C10CC90405F5106000EB4410016105F579 +:10886000106000EB44100069AF49084005F5106145 +:1088700001EB44110861F168B0690844401EB0FB87 +:10888000F1F0A949C94301EAC04005F5106101EBC7 +:1088900044110969084305F5106101EB44110861B1 +:1088A00005F5106000EB44100069B169C1F31201D5 +:1088B000084305F5106101EB441108613079012886 +:1088C00017D105F5106000EB4410006920F0C0419D +:1088D00005F5106000EB4410016105F5106000EB38 +:1088E0004410006940F0005105F5106000EB4410A1 +:1088F000016100E07FE0012F36D1706928B105F5F4 +:10890000106000EB441071694161307901281ED17B +:1089100040F60800405900F4807060B905F5106019 +:1089200000EB4410006840F0005105F5106000EBCA +:10893000441001600BE005F5106000EB4410006886 +:1089400040F0805105F5106000EB4410016005F522 +:10895000106000EB4410006840F0044105F5106021 +:1089600000EB44100160DCE005F5106000EB441002 +:10897000006840F0044105F5106000EB4410016010 +:10898000307901280FD0B0690028ECD040F63400CF +:108990004059317801F00F0201219140084340F61F +:1089A00034014851BDE040F60800405900F48070A1 +:1089B00060B905F5106000EB4410006840F000510C +:1089C00005F5106000EB441001600BE005F5106048 +:1089D00000EB4410006840F0805105F5106000EB9A +:1089E000441001600097308B83B232784846316979 +:1089F00000F0BEFA95E005F5306000EB4410006928 +:108A0000C10CC90405F5306000EB4410016105F5A7 +:108A1000306000EB441000694349084005F53061BF +:108A200001EB44110861B069D0B905F5306000EB85 +:108A300044100069F168C1F31201084305F5306183 +:108A400001EB4411086105F5306000EB441000694A +:108A500040F4002105F5306000EB4410016128E08E +:108A6000F168B0690844401EB0FBF1F01FFA80F8CD +:108A7000F06800FB08F0F06105F5306000EB441091 +:108A800000692949C94301EAC841084305F5306135 +:108A900001EB4411086105F5306000EB44100069FA +:108AA000F169C1F31201084305F5306101EB44118E +:108AB0000861012F07D1306928B105F5306000EB5E +:108AC000441031694161307901281ED140F6080017 +:108AD000405900F4807060B905F5306000EB441037 +:108AE000006840F0005105F5306000EB4410016073 +:108AF0000BE005F5306000EB4410006840F0805159 +:108B000005F5306000EB4410016005F5306000EBC6 +:108B10004410006840F0044105F5306000EB44105B +:108B200001600020BDE8F883FFFF07E078B5034649 +:108B30000024009400201A464C78012C35D10C7882 +:108B400002F5106505EB4414246804F00044B4F108 +:108B5000004F60D10C7805EB4414246844F00066A3 +:108B60000C7805EB441426600C7805EB441424685B +:108B700044F080460C7805EB4414266000BF009C4E +:108B8000641C009442F21075009CAC4201D9012093 +:108B90000AE00C7802F5106505EB4414246804F033 +:108BA0000044B4F1004FEAD035E00C7802F53065AE +:108BB00005EB4414246804F00044B4F1004F2AD1BA +:108BC0000C7805EB4414246844F000660C7805EB3F +:108BD000441426600C7805EB4414246844F0804665 +:108BE0000C7805EB4414266000BF009C641C0094C4 +:108BF00042F21075009CAC4201D901200AE00C78C9 +:108C000002F5306505EB4414246804F00044B4F127 +:108C1000004FEAD000BF78BD0146886840F00100EF +:108C2000886000207047000008B5014600200090D1 +:108C300000BF0098401C00900F4A0098904201D954 +:108C4000032008BD086900F000400028F1D0002092 +:108C500000901020086100BF0098401C0090064A58 +:108C60000098904201D90320EBE7086900F010005A +:108C70001028F1D00020E4E7400D030008B50246BB +:108C80000020009000BF0098401C0090104B0098FE +:108C9000984201D9032008BD106900F00040002867 +:108CA000F1D000200090202040EA8110106100BF28 +:108CB0000098401C0090064B0098984201D9032070 +:108CC000E9E7106900F020002028F1D00020E2E759 +:108CD000400D030010B501460B4640F60804E45869 +:108CE00004F006020AB9002006E0022A01D0062A92 +:108CF00001D1022000E00F2010BD0146486900F0BC +:108D00000100704701460B4640F61800C258001D8E +:108D1000C058024090B2704701460B4640F618001A +:108D2000C258001DC0580240100C704770B5024672 +:108D300013464FF40166F45840F63406F55801F036 +:108D40000F0625FA06F606F0010644EAC61403F5F6 +:108D5000106606EB4116B66806EA040070BD10B551 +:108D60000246134603F5306404EB4114A06840F654 +:108D70001404E458204010BD014648698A69104037 +:108D800070472DE9F04104460D46274628464FEA34 +:108D9000920C02F0030300210AE04FF4805858F8C7 +:108DA0000780C0F80080401C401C401C401C491C2F +:108DB0006145F2D39BB100214FF4805858F8076009 +:108DC00000BF4FEAC10826FA08F880F80080491C65 +:108DD000401CA3F101081FFA88F3002BF1D1BDE874 +:108DE000F08170B504460E460025E06820F0C040D2 +:108DF000E060012E10D1E06840F00050E06000BF5C +:108E00000120F8F715FA6D1C2046FFF776FF0128C0 +:108E100015D0322DF4D312E07EB9E06840F08040E6 +:108E2000E06000BF0120F8F703FA6D1C2046FFF751 +:108E300064FF20B1322DF5D301E0012070BD322D49 +:108E400001D10120FAE70020F8E710B502460B46F1 +:108E50001146D1F8000820F4FE60C1F80008D1F8EE +:108E600000084FF4FE6404EA03142043C1F800082C +:108E7000002010BD02461346D3F800080843C3F88B +:108E8000000800207047000030B503461446022C4D +:108E900049D12D48814204D32C48814201D20F226E +:108EA00045E02A48814204D32948814201D20E225A +:108EB0003DE02748814204D32648814201D20D2259 +:108EC00035E02448814204D32348814201D20C2258 +:108ED0002DE02148814204D32048814201D20B2257 +:108EE00025E01E48814204D31D48814201D20A2256 +:108EF0001DE01B48814204D31A48814201D2092255 +:108F000015E01848814204D31748814201D2082253 +:108F10000DE01548814204D31448814201D2072252 +:108F200005E0062203E00CB9092200E00922D86816 +:108F300020F47050D860D8684FF4705505EA822547 +:108F40002843D860002030BDC0ACD800C0E1E400A8 +:108F50000024F40080730601A0491A01002D31019C +:108F600040A44C0100366E0120ABA6010048E80188 +:108F70002DE9F04304460D461E46DDF81CC0A04610 +:108F80002946BCF1000F12D1F01C870800230CE029 +:108F9000D1F8009008F5805000EB0230C0F8009046 +:108FA000491C491C491C491C5B1CBB42F0D30020D6 +:108FB000BDE8F08300BFFEE70FB4084B10B504A96D +:108FC00002AA039800F0F6FA044602A9002000F075 +:108FD000C0FF204610BC5DF814FB0000539F000842 +:108FE0007CB50C001D461646014601D0601E00E00F +:108FF0000020CDE90010064B6A462946304600F0B5 +:10900000D9FA002C02D0009A002111707CBD00001A +:109010005B9E000802480068C0F302207047000011 +:109020000CED00E010B5002804DB0A07130E054A1A +:10903000135406E00A07140E034A00F00F031B1F27 +:10904000D45410BD00E400E018ED00E002E008C8D0 +:10905000121F08C1002AFAD170477047002001E0B2 +:1090600001C1121F002AFBD170472DE9FC410446C3 +:10907000A089401E80B200906089401E83B2002209 +:1090800011462046266FB0472068006A00680068D5 +:109090004FF6BF7108402168096A096808602068B6 +:1090A000006A0068006840F400602168096A096885 +:1090B00008602068006A0068006840F0400021688D +:1090C000096A0968086020680169D1E90401CDE9ED +:1090D000000120680669F7683B4696E80700B84734 +:1090E000002508E0608A2168096A0968C86020686C +:1090F00000F047FF6D1C6089A1894843A842F1D860 +:10910000206800F035FF20680169D1E90401CDE94C +:10911000000120680669D6E902733A46D6E90001E3 +:10912000B8472068006A006800684FF6BF710840C1 +:109130002168096A096808602068006A0068006898 +:109140004FF2FF7108402168096A096808602068C9 +:10915000006A0068006840F040002168096A0968F8 +:109160000860BDE8FC8100002DE9FF5F82B00021AE +:10917000DDE90430020DDDF840B0034318D044F6B9 +:109180001050A2F2FF3242431514119801281FD04B +:10919000A5EB0B00401C5FEA000A4FF000064E4FA3 +:1091A000DFF83891B046504615D5CAF1000413E0F7 +:1091B000119801244AA3012801D16FEA0B010298FA +:1091C000119AC0E90031C0E9024206B0BDE8F09F43 +:1091D000CBF10000DFE704460021404A491842EB8A +:1091E0000450CDE9001012E0E00707D032463B46BC +:1091F00040464946F7F7AEF98046894632463B4637 +:1092000010461946F7F7A6F906460F466410002CDB +:10921000EAD1DDE90401DDE90023BAF1000F06DA45 +:10922000F7F798F942464B46F7F794F905E0F7F758 +:10923000EFFA42464B46F7F7EBFA04460E46002299 +:10924000284BF7F76DFB03D84FF0FF30014607E0DE +:109250000022254B20463146F7F7D5F8F7F747FBB4 +:10926000102409E0002C0ADB0A220023F7F70AF891 +:10927000039B30321A55641E50EA0102F2D1641C7D +:10928000039AC4F111031444119A012A03D0012254 +:1092900008430DD10AE0084304D000204FF0110B21 +:1092A000119072E7A3EB0B056D1E0DE05B4504DD2D +:1092B0004FF0000205F1010504E003DA4FF000026F +:1092C000A5F10105002AECD002981199C0E90231FC +:1092D000C0E9004579E70000000014400000F03FBD +:1092E000300000000000F0430000E03F014601F1C3 +:1092F000100000E0001D02681AB9024A126890428C +:10930000F8D37047B400002070B504460D460CB188 +:10931000012100E00021084640F20511F7F73AFC70 +:109320000DB1012100E0002108464FF48371F7F7E9 +:1093300031FC002084F831002562206A0068006852 +:1093400040F04000216A0968086070BD7CB50446A1 +:109350000A20F7F76DFF20680169D1E90401CDE922 +:10936000000120680569EE68334695E80700B047BC +:109370003621206800F083FE0021206800F0B9FE4D +:109380003A21206800F07BFE0521206800F0B1FE44 +:10939000B221206800F073FE0C21206800F0A9FEC5 +:1093A0000C21206800F0A5FE0021206800F0A1FE3D +:1093B0003321206800F09DFE3321206800F099FEE3 +:1093C000B721206800F05BFE3521206800F091FE97 +:1093D000BB21206800F053FE1921206800F089FEAF +:1093E000C021206800F04BFE2C21206800F081FE97 +:1093F000C221206800F043FE0121206800F079FEC0 +:10940000C321206800F03BFE1221206800F071FEAD +:10941000C421206800F033FE2021206800F069FE9E +:10942000C621206800F02BFE0F21206800F061FEAD +:10943000D021206800F023FEA421206800F059FE0E +:10944000A121206800F055FEE021206800F017FE01 +:10945000D021206800F04DFE0421206800F049FE74 +:109460000D21206800F045FE1121206800F041FE2A +:109470001321206800F03DFE2B21206800F039FE0A +:109480003F21206800F035FE5421206800F031FEB5 +:109490004C21206800F02DFE1821206800F029FEE4 +:1094A0000D21206800F025FE0B21206800F021FE30 +:1094B0001F21206800F01DFE2321206800F019FE06 +:1094C000E121206800F0DBFDD021206800F011FED2 +:1094D0000421206800F00DFE0C21206800F009FE38 +:1094E0001121206800F005FE1321206800F001FE24 +:1094F0002C21206800F0FDFD3F21206800F0F9FDDF +:109500004421206800F0F5FD5121206800F0F1FDB4 +:109510002F21206800F0EDFD1F21206800F0E9FDFB +:109520001F21206800F0E5FD2021206800F0E1FD0A +:109530002321206800F0DDFD2121206800F09FFD3F +:109540001121206800F09BFD7820F7F771FE29219A +:10955000206800F094FD206800F00AFD2068016991 +:10956000D1E90401CDE9000120680569D5E902636C +:109570003246D5E90001B04702212046E26D90470E +:10958000002060822046A16F884700207CBD00003B +:1095900010B50648046803E02046FFF7A7FE04461E +:1095A000034800688442F7D310BD0000B0000020DB +:1095B000B40000202DE9FF4F95B09A468846064634 +:1095C0000025EEE1252877D100242746F94A01211C +:1095D000039400E0044316F8013F203B01FA03F036 +:1095E0001042F7D130782A2811D06FF02F0330784D +:1095F000A0F13002092A16D8039A44F0020402EBC3 +:10960000820203EB42021044761C0390EFE758F805 +:10961000042B0392002A03DA504244F400540390CE +:1096200044F00204761C30782E2816D116F8010F6B +:1096300044F004042A280DD06FF02F023078A0F1F6 +:109640003003092B09D807EB870302EB4303C71844 +:10965000761CF3E758F8047B761C30786C280FD022 +:1096600006DC4C2817D068280DD06A2814D104E0F5 +:10967000742810D07A280FD10DE044F400140AE0C9 +:1096800044F4801401E044F440147278824202D120 +:1096900004F58014761C761C307866280BD013DC19 +:1096A000582877D009DC002875D04528F6D0462800 +:1096B000F4D047281AD193E118E0632835D0642804 +:1096C00079D0652812D18BE1702873D008DC672827 +:1096D000F1D069286FD06E280DD06F2806D1ACE08C +:1096E00073282CD0752874D0782853D052461799F7 +:1096F00090476D1C54E1C4F30250022809D003289E +:109700000DD0D8F8001004280DD00D6008F1040821 +:1097100046E1D8F80010EA17C1E90052F6E7D8F898 +:1097200000100D80F2E70D70F0E718F8041B8DF8BB +:10973000001000208DF80100EB46012003E058F8EE +:1097400004BB4FF0FF3061074FF0000102D40DE081 +:1097500009F101018946B9420FDA8145F8DB1BF8AE +:1097600009100029F4D108E009F10101894681427C +:10977000FADB1BF809100029F6D103985346A0EB39 +:10978000090721463846179A00F080FA284400EB72 +:10979000090507E044E008E10DE01BF8010B524623 +:1097A00017999047B9F10109F7D253462146384637 +:1097B000179AF2E039E00A21C4F302524FF0000B8D +:1097C0000091022A06D058F8040BC117032A09D0C9 +:1097D0000AE023E008F1070020F00702F2E80201A6 +:1097E000904605E000B2C117042A01D140B2C1176A +:1097F000002906DA0A460021404261EB02012D22CF +:1098000002E0220504D52B228DF80420012203E07A +:10981000E20701D02022F7E7914657E00A2100E055 +:1098200010214FF0000B00910BE010214FF0000BC6 +:1098300044F004040827009103E008204FF0000BD7 +:109840000090C4F30252022A05D058F8040B0021FC +:10985000032A08D008E008F1070020F00702F2E828 +:109860000201904603E080B2042A00D1C0B24FF05A +:10987000000922072AD53278702A07D0DDF800C007 +:109880008CF0100C5CEA0B0C05D00EE040228DF839 +:109890000420012208E050EA010306D030238DF8AD +:1098A00004308DF8052002229146009B83F00803C6 +:1098B00053EA0B030AD150EA010201D1620705D530 +:1098C00030228DF804204FF001097F1E3278582A8B +:1098D00004D039A20C920CAA02920BE03BA2F9E749 +:1098E0005B46009AF6F7CEFC0C9B9B5C029A521EDC +:1098F0000292137050EA0102F2D1029804A9081AE8 +:1099000000F1200B600702D524F4803400E0012729 +:109910005F4502DDA7EB0B0000E0002000EB0B0130 +:10992000009003984944401A0390E00306D453463C +:109930002146179A039800F0A9F90544002706E08C +:1099400001A85246C05D179990476D1C7F1C4F457A +:10995000F6DBE0030CD553462146179A039800F036 +:1099600095F9054404E030205246179990476D1C44 +:109970000099481E00900029F5DC08E00298029941 +:1099800052460078491C0291179990476D1CBBF113 +:109990000001ABF1010BF1DC5BE100F065F905447E +:1099A000761C307800287FF40DAE19B02846BDE84B +:1099B000F08F00000928010030313233343536375A +:1099C000383961626364656600000000303132330B +:1099D00034353637383941424344454600000000AB +:1099E000600700D4062708F1070020F00700F0E820 +:1099F0000223804603F0004C5FEA0C0001D097A0E0 +:109A000009E0200501D596A005E0E00701D095A06A +:109A100001E0AFF24C001390307823F0004365284A +:109A20000CD006DC452809D046281DD047287FD118 +:109A30003BE0662818D067287AD136E00021112F44 +:109A400001DB112000E0781CCDE9000104A90CA87D +:109A5000FFF78AFBDDE90D010C9A4FF0000B07F1CF +:109A60000109109200914EE04FF000400097CDE9BF +:109A7000011004A90CA8FFF777FBDDE90D020C9B90 +:109A80000F994FF0000B91461093009211B9791C79 +:109A900000EB0109B7EB090003D4C0F1FF3B07F16C +:109AA0000109A9EB0700019042E0012F00DA01272C +:109AB0000021112F01DD112000E03846CDE9000121 +:109AC00004A90CA8FFF750FBDDE90D010C9A0091E9 +:109AD0004FF0000BB946109221070FD4009A4A4567 +:109AE00003DA914601E0A9F10109B9F1010F05DDA1 +:109AF000109AA9F10101515C3029F4D0B84202DA80 +:109B000010F1040F03DA0121CDE9011010E0002863 +:109B100003DC8344A9EB000102E0411C494500DD60 +:109B20008946A0EB0B00401C01904FF000400290D2 +:109B3000200705D40198484502DB4FF0FF30019023 +:109B400000208DF84B0002980DF14B07B0F1004F4B +:109B500025D002200C902B200D90029800280CDAC2 +:109B6000404202902D200D9007E00A210298F6F75E +:109B7000ABFD3031029007F8011D0C99481E0C9086 +:109B80000029F2DC02980028EFD1791E0D980870A8 +:109B9000307800F0200040F0450007F8020D11A8D1 +:109BA000C01BC01D02901398007800B1012000EB8B +:109BB0000901019801EBE071029801440398401AF1 +:109BC000401E0390E00306D453462146179A03989B +:109BD00000F05CF805441398007818B152461799C4 +:109BE00090476D1CE00323D553462146179A0398EE +:109BF00000F04CF805441BE0BBF1000F07DB0098B8 +:109C0000584504DD1098179910F80B0001E01799DA +:109C100030205246904701980BF1010B401E05F190 +:109C20000105019004D12E205246179990476D1CD2 +:109C3000B9F10001A9F10109DEDC05E017F8010B1B +:109C40005246179990476D1C0299481E02900029B0 +:109C5000F4DC53462146179A03989EE62D00000037 +:109C60002B000000200000002DE9F04104460025F3 +:109C70001E461746880404D405E039462020B04724 +:109C80006D1C641EF9D52846BDE8F0812DE9F04130 +:109C9000044600251E469046C80301D5302700E043 +:109CA0002027880404D505E041463846B0476D1C9E +:109CB000641EF9D52846BDE8F0810FB410B5BDF893 +:109CC0000C100298F7F7C2FB012802D110BC5DF816 +:109CD00014FB0020FAE70FB410B5BDF80C100022F9 +:109CE0000298F7F7C5FB10BC5DF814FB0FB410B574 +:109CF000BDF80C1001220298F7F7BAFB10BC5DF812 +:109D000014FB2DE9FC4704460D4616461F46DDF8B8 +:109D1000288020680169D1E90401CDE900012068AB +:109D2000D0F810C0DCF80C904B469CE80700C84700 +:109D30002A21206800F0A3F9E2892A4491B2206820 +:109D400000F0C6F9E2893A4491B2206800F0C0F907 +:109D50002B21206800F093F9228A324491B22068C6 +:109D600000F0B6F9228A424491B2206800F0B0F9BE +:109D70002C21206800F083F9206800F0F9F82068B1 +:109D80000169D1E90401CDE900012068D0F810C0D3 +:109D9000DCE902934A46DCE90001C847BDE8FC87DC +:109DA0002DE9FC4104460D46257220680169D1E980 +:109DB0000401CDE9000120680669F7683B4696E892 +:109DC0000700B8475DB93621206800F058F97021C6 +:109DD000206800F08EF90020E08120822AE0022D28 +:109DE0000BD13621206800F04AF90021206800F0EC +:109DF00080F90020E08120821CE0012D0CD1362169 +:109E0000206800F03CF9A021206800F072F9502091 +:109E1000E081002020820DE0032D0BD13621206847 +:109E200000F02DF9C021206800F063F90020E081E6 +:109E300050202082206800F09BF820680169D1E959 +:109E40000401CDE9000120680669D6E902733A46AB +:109E5000D6E90001B847BDE8FC814A68002A06D06F +:109E60000A68531C0B6010704868401E48607047B9 +:109E70002DE9FC4105460E4600270DB1012100E009 +:109E800000210846DD21F6F785FE2C460CB10121A4 +:109E900000E0002108463621F6F77CFEA06960B19B +:109EA000A169D1E90401CDE90001D4F818C0DCF8BA +:109EB0000C8043469CE80700C04700BF284607F0D7 +:109EC0001BFB3146284607F048FB0746284607F0AB +:109ED000F7FA3846BDE8FC812DE9FC4705460E46F9 +:109EE00017464FF000080DB1012100E0002108469F +:109EF000F021F6F74FFE2C460CB1012100E00021C5 +:109F000008462821F6F746FEA06960B1A169D1E9AB +:109F10000401CDE90001D4F818C0DCE902934A46F7 +:109F2000DCE90001C84700BF284607F0E5FA002435 +:109F300007E03178284607F010FB8046761C601C4D +:109F400084B2BC42F5DB284607F0BAFA4046BDE8C9 +:109F5000FC870A68531C0B60107070470FB410B573 +:109F6000BDF80C100298F7F779FA10BC5DF814FBF5 +:109F700000BF016A0968896801F080010029F8D1F1 +:109F8000704700BF016A0968896801F00201002971 +:109F9000F8D070472DE9FC4104460E46174620686C +:109FA000006A006800684FF6BF7108402168096ABE +:109FB000096808602068006A0068006840F4006072 +:109FC0002168096A096808602068006A00680068FA +:109FD00040F040002168096A09680860206801694A +:109FE000D1E90401CDE900012068D0F810C0DCF807 +:109FF0000C8043469CE80700C047002509E036F87E +:10A0000015002168096A0968C8602068FFF7B9FF70 +:10A010006D1CBD42F3D32068FFF7AAFF20680169D9 +:10A02000D1E90401CDE900012068D0F810C0DCE9D5 +:10A0300002834246DCE90001C0472068006A0068EC +:10A0400000684FF6BF7108402168096A0968086016 +:10A050002068006A006800684FF2FF7108402168BC +:10A06000096A096808602068006A0068006840F0B2 +:10A0700040002168096A09680860BDE8FC812DE993 +:10A08000FC4104460D462046FFF772FFE169D1E925 +:10A090000401CDE90001E669F7683B4696E8070050 +:10A0A000B847206A0068C5602046FFF76AFF20466F +:10A0B000FFF75EFFE169D1E90401CDE90001E6693E +:10A0C000D6E902733A46D6E90001B847BDE8FC81FB +:10A0D00070B504460D462812216A0968C8602046FA +:10A0E000FFF74FFF206A0068C5602046FFF749FF71 +:10A0F00070BD70B504460D46206A0068C5602046F4 +:10A10000FFF73FFF70BD2DE9F84F04460D46164698 +:10A110001F46DDE90A89781B401CA8EB0601491C93 +:10A1200000FB01FACDF800803B4632462946204626 +:10A13000D4F870C0E0471FFA8AF249462046FFF77C +:10A1400029FFBDE8F88F00001CB507F00DFB05489E +:10A15000012100238A02CDE9001003A1064808F07E +:10A160008DFB1CBD7C000020627573696E65737386 +:10A170005F7461736B000000EDA3000810B51468F4 +:10A18000641C8C4201D2146803551468641C14606A +:10A1900010BD00002DE9F04F2DED068B83B08146F8 +:10A1A0008A469346B0EE408AF0EE608A1D4651EC36 +:10A1B000180BF6F752FA04462046F6F73DFA41EC42 +:10A1C0001A0B53EC182BF6F7C2F941EC190B9FED63 +:10A1D0002B0B53EC102B51EC180BF6F75DFA0CD24D +:10A1E0002D235A4651464846FFF7C8FF644251ECBA +:10A1F000190B81F0004141EC190B0020009023461F +:10A200005A4651460190484600F080F82E235A469F +:10A2100051464846FFF7B2FF002D01DB284600E01B +:10A2200006208046002622E09FED160B53EC102BF3 +:10A2300051EC190BF6F78EF941EC190B51EC190B97 +:10A24000F6F70BFA074607F13000C3B25A465146FB +:10A250004846FFF793FF3846F6F7EEF941EC1A0B44 +:10A2600053EC192BF6F773F941EC190B761C4645A4 +:10A27000DADB03B0BDEC068BBDE8F08F0000000018 +:10A280000000000000000000000024402DE9F0471D +:10A2900088B006460F4690461C46DDF840900025E3 +:10A2A000B9F1000F01D00FA000E013A0824600BF5B +:10A2B00004F00F001AF8002028466D1C0DF800204D +:10A2C0002409002CF4D106E01DF805304246394639 +:10A2D0003046FFF753FF281EA5F10105F4D108B061 +:10A2E000BDE8F087303132333435363738394142C2 +:10A2F00043444546000000003031323334353637B0 +:10A300003839616263646566000000002DE9FF4F23 +:10A3100091B083461C46DDE91E7800254FEAD479CA +:10A32000204608B901230EE00021C20F02B14042CD +:10A3300000BF491C0A2390FBF3F00028F9D10AB1B1 +:10A340004B1C00E00B469A460026002F03DD5745C4 +:10A3500001D9A7EB0A06B8F1000F08D13EB12020C1 +:10A36000334600905846DDE9121200F06CFEB9F158 +:10A37000000F00D0644200BF0A2094FBF0F100FB04 +:10A3800011403030C2B228466D1C01A90A540A207F +:10A3900094FBF0F4002CEFD1B9F1000F03D02D2283 +:10A3A00028466D1C0A5406E001A8435D5846DDE9C5 +:10A3B0001212FFF7E3FE281EA5F10105F4D1B8F152 +:10A3C000000F08D03EB12020334600905846DDE90A +:10A3D000121200F038FE15B0BDE8F08F10B500F095 +:10A3E000E7F901F05BFC01F025FD10BD05F062F915 +:10A3F00005F0CAFA4FF4FA6007F090FB00BF01F0D5 +:10A40000D3FC00F069FA05F0BFFA002000F044FB2D +:10A410004FF47A7007F082FBF1E700002DE9F0417C +:10A4200090B0804600BF3D48D0F8B400046A0026D2 +:10A4300000250CB9012000E0002018B1002010B068 +:10A44000BDE8F08128466D1C4DF8204053E000BF68 +:10A45000102D04DBCC22324932A002F083F800BF79 +:10A46000681E05465DF82040274600BF00BF2FB993 +:10A4700040F2B332344935A002F074F800BF786A74 +:10A4800008B1012000E0002020B128466D1C626A5E +:10A490004DF82020274600BF00BF2FB94FF491622E +:10A4A00034492AA002F05EF800BF97F82800C0F3F4 +:10A4B000800000B11FE0608D020904F108014046F0 +:10A4C00000F0D6FDB0B12646274600BF00BF2FB929 +:10A4D0004FF4677228491DA002F044F800BF386AA3 +:10A4E00008B1012000E0002020B128466D1C226A3E +:10A4F0004DF8202000BF002DA9DC6EB1304604F0DD +:10A50000CBFC08B130469AE7F06904F0C5FC08B10D +:10A51000F06994E7002092E7304690E74C2801204C +:10A520006E3401082E2E5C557365725C73797374FA +:10A53000656D5C73676C5C636F72655C73676C5FA1 +:10A540006576656E742E6300333401082E2E5C55DB +:10A550007365725C73797374656D5C73676C5C6949 +:10A560006E636C7564655C73676C5F636F72652E98 +:10A57000680000004734010821340108F0B595B0A7 +:10A5800004460E46002500BF2CB940F27D522849F2 +:10A5900028A001F0E7FF00BF28466D1C01A941F883 +:10A5A00020403AE000BF102D05DB40F281522049E7 +:10A5B00020A001F0D7FF00BF681E054601A951F891 +:10A5C0002040606A20B128466D1C626A41F8202054 +:10A5D000204604F087FC00B11FE02146304605F01C +:10A5E0008DF9C8B10F20ADF8500000BFA06928B99F +:10A5F00040F28E520E490FA001F0B4FF00BF11AA25 +:10A6000021463046A3699847206A28B128466D1C28 +:10A6100001A9226A41F8202000BF002DC2DCB768E2 +:10A620000D48394642693046904700BF15B0F0BD2D +:10A630007E3301082E2E5C557365725C73797374DA +:10A64000656D5C73676C5C636F72655C73676C5F90 +:10A65000636F72652E6300004C280120F0B503463D +:10A660000024012901D0022904D101F10C00C1B25A +:10A67000581E83B24D1C05EB4505052695FBF6F5E6 +:10A68000022606FB012635441D441846DE1703EB5F +:10A69000967605EBA605642693FBF6F6AD1B4FF404 +:10A6A000C87693FBF6F63544072695FBF6F706FBCE +:10A6B0001755ECB2601CC0B2F0BD00002DE9F041AE +:10A6C00005460E4618273946002000F0B9FB04461F +:10A6D0000CB1012100E0002108463621F6F75AFAB4 +:10A6E0002560A6800548A0600548E0600548206117 +:10A6F000054860612046BDE8F0810000ED9C00083F +:10A70000D79C00085D9F0008BB9C000800BFEFF3CA +:10A71000058008B1012070470020FCE70FB470B538 +:10A720009C252946002000F08BFB04460CB101213A +:10A7300000E0002108461C21F6F72CFA204604A967 +:10A74000382203E011F8013B00F8013B131EA2F18F +:10A750000105AAB2F6D100BF012184F898100220A9 +:10A7600020B1012803D0022807D101E00CE00BE062 +:10A7700004F1380000F070F906E0204600F007F818 +:10A78000002070BC5DF814FB00BF2046F9E710B54F +:10A7900004460CB1012100E0002108461421F6F71F +:10A7A000F9F900BF2146002000F020FB00BF10BDDA +:10A7B00030B5B3B04FF400614348FFF77FFF2F90EF +:10A7C0004FF480514048FFF779FF329038223F49DB +:10A7D0001EA8F5F7B9FD002004902FA80FC88DE83A +:10A7E0000F0001202CA90EC906F028FE1E901E980D +:10A7F0003749C26A904723221EA90BA8F5F7A4FD8A +:10A800009DF89B008DF84F00142227A914A8F5F796 +:10A810009BFD28220FA96846F5F796FD0BA80FC8E7 +:10A82000FFF77CFF2B490861096909B1012100E0AC +:10A830000021084640F22F11F6F7ACF925480069CF +:10A840000068C169D1E90401CDE90001214800692E +:10A850000068C4691F4800690068C069856894E899 +:10A860000F00A8471B48006900680169D1E904018D +:10A87000CDE90001174800690068046915480069BE +:10A8800000680069856894E80F00A84700224FF42B +:10A8900000510D48F6F7ECFD0E4A10691269916BF4 +:10A8A0008847012251030848F6F7E2FD14220749C0 +:10A8B000383119A8F5F748FD19A803F03FF903F05E +:10A8C000E9FB33B030BD0000000C0240FC2E010853 +:10A8D0000C060020A04400207FB5494800680028ED +:10A8E00073D104F00DF90020039000BF4548D0F863 +:10A8F000B4000446039904F0A7FE002003F08EFC88 +:10A90000054646220021284604F00AFD1C22F021BB +:10A91000284604F0A9FD3CA1284603F0D8FC3E4996 +:10A92000284603F0CBFC3D48006802902846029977 +:10A9300003F0E4FC0021284603F0D2FC002003F0E1 +:10A940006DFC054664220021284604F0E9FC1C2227 +:10A95000F021284604F088FD31A1284603F0B7FC19 +:10A960002D49284603F0AAFC2C48001D00680190E0 +:10A970002846019903F0C2FC0021284603F0B0FCF0 +:10A98000002003F04BFC1E490860822200211C4875 +:10A99000006804F0C5FC1C22F0211948006804F08E +:10A9A00063FD1D491648006803F088FC1B48083009 +:10A9B0000068009012480099006803F09FFC002195 +:10A9C0000F48006803F08CFC00BF1A48007B19494F +:10A9D000C97A184A927A174BDB79CDE90032CDE972 +:10A9E000021014488379808800F5FA6212A1194890 +:10A9F000FEF7E2FA17490248006803F068FC7FBDE1 +:10AA0000800000204C28012053544D3332205254F2 +:10AA10004320546573740000A85D0108C82E010826 +:10AA20005265736F6C7574696F6E3A20323430788A +:10AA300032343000A044002025642D253032642DAE +:10AA40002530326420253032643A253032643A258C +:10AA5000303264007457002010B504460CB1012157 +:10AA600000E000210846FC21F6F794F80548206034 +:10AA7000054860620548A0630548E0630548206416 +:10AA800010BD00004D930008A19D0008039D000823 +:10AA900007A100086B90000810B504462CB94FF4CC +:10AAA00000510348F6F7DAFC00E000BF00BF10BD1C +:10AAB0000008024010B504462146002000F002F8CC +:10AAC00010BD00002DE9F04105460C460027B846B0 +:10AAD00000260DB1284600E0184805460CB1E8688C +:10AAE00010B10020BDE8F0810027B846002100BF6A +:10AAF00004EBC100406838B954F8310020B90E4663 +:10AB00000EB90020EEE70FE007EB080054F8312003 +:10AB1000904201D90020E5E754F8317004EBC10000 +:10AB2000D0F80480491CE3E700BF0EB90020D9E744 +:10AB30002146284600F0F2FED4E700002C52012006 +:10AB400010B504462146002000F002F810BD0000B8 +:10AB500070B504460D460CB1204600E0034804469B +:10AB60002946204600F022FF70BD00002C52012033 +:10AB700010B504462146002000F002F810BD000088 +:10AB800070B503460020C1B10BB11C4600E00B4C70 +:10AB9000234611B1A1F1080400E00024224662B16D +:10ABA000546804F0004444B1054E1468B44204D122 +:10ABB000546824F00044A4F1080070BD2C52012018 +:10ABC000EFBEADDE10B5044622460021084600F077 +:10ABD00001F810BD2DE9F04104460D461646002748 +:10ABE0000CB1204600E0054804463246294620467E +:10ABF00000F02BFE07463846BDE8F0812C520120BC +:10AC0000F6F74EFCFBF77AF8F9F7E2FCF9F78AFC65 +:10AC1000F9F7F6FDF9F70EFEF9F7B8FCF9F72EFE95 +:10AC2000F9F70AFE002000F04BF8012000F048F888 +:10AC3000FFF7D4FBFFF788FAF9F7B6FC00F033F919 +:10AC400000BFFEE701460020842901D0CA1C104441 +:10AC5000704700002DE9F04104460E461548005D9E +:10AC600038B9144818380168204688470120BDE8E3 +:10AC7000F081114850F82400B04219D90F4850F81B +:10AC80002400B6FBF0F70B48083850F8240030F8E1 +:10AC90001780002508E000210648083850F82400F5 +:10ACA0007A1920F812106D1C4545F4DB0020DEE710 +:10ACB0000120DCE7D0000020702F0108682F010878 +:10ACC00010B504460C4951F824104A000B4951F8BC +:10ACD0002400002100F0C8F8094951F82420074950 +:10ACE000083951F82400002100F0BEF80121034882 +:10ACF0000830015510BD0000602F0108C800002079 +:10AD0000702F01082DE9F04704460F460025A9469B +:10AD10002348005D20B9224818380168204688473A +:10AD20001FB94FF0FF30BDE8F0871E4850F82400EF +:10AD3000B7FBF0F61B4850F82400B7FBF0F100FB1E +:10AD4000117000B1761C184850F82400451E22E00E +:10AD50001348083850F8240030F8150010B909F1EC +:10AD6000010901E04FF00009B14513D14FF000088F +:10AD700009E00B48083850F8240005EB080220F8D9 +:10AD8000126008F10108B045F3D3064850F82400DA +:10AD90006843C8E76D1E002DDADA4FF0FF30C2E7D6 +:10ADA000D0000020682F0108602F010810B501466F +:10ADB0000023002207E00B4850F8210030F8120071 +:10ADC00000B15B1C521C084850F821009042F2D898 +:10ADD00064205843044C54F82140B0FBF4F0C0B256 +:10ADE00010BD0000C8000020602F01082DE9F041CF +:10ADF00004460D460DB9BDE8F0810F4850F8240017 +:10AE00002E1A0E4850F82400B6FBF0F10A4808301C +:10AE100050F8240030F81100084951F8241000FBC4 +:10AE200001F73A460021284600F01EF83146204638 +:10AE3000FFF710FF00BFDEE7C0000020682F010809 +:10AE400070B504460E4631462046FFF75BFF0546C7 +:10AE5000681C08B9002070BD024850F8240028443E +:10AE6000F9E70000C000002030B5034601E003F818 +:10AE7000011B141EA2F10102F9D130BD70B50446C8 +:10AE800025460DB1294600E00121084606F046FEA0 +:10AE9000002070BD10B507F081FD012801D1002010 +:10AEA00010BD0120FCE710B506F006FF002010BD24 +:10AEB00010B5FFF72BFC10B107F086FD10BD07F0B1 +:10AEC0007DFDFBE7F8B504460D46A06840B1E0689B +:10AED00030B10020009094E80F0007F085F8F8BD2D +:10AEE0000022D4E9000107F052F8F8E72DE9FF410C +:10AEF00007460D4614460295002001903DB980207A +:10AF000000909DE8070087E80700BDE8FF8100206A +:10AF100003900026601C08B9761E03E014B1264693 +:10AF200006B90126FFF7F2FBB0B103AA01A9284632 +:10AF300007F01CFB012802D11020009001E0002046 +:10AF400000900398B8B14FF080500E490860BFF3ED +:10AF50004F8FBFF36F8F0EE0324601A9284607F0EE +:10AF600051FA012802D11020009004E00EB900200F +:10AF700000E0402000909DE8070087E8070000BF40 +:10AF8000C3E7000004ED00E077B581B00646144643 +:10AF900000200090254605B90125FFF7B7FBA8B1B1 +:10AFA00000236A4602A9304607F0AEF9012802D014 +:10AFB000FF2004B070BD009890B14FF08050094957 +:10AFC0000860BFF34F8FBFF36F8F09E000232A465D +:10AFD00002A9304607F0C4F8012801D0FF20E8E7B5 +:10AFE0000020E6E704ED00E07FB504460D46606909 +:10AFF00098B1A06988B1B4F90800FFF723FE0646AE +:10B00000D4E90510CDE9006102902B462269D4E90C +:10B01000001007F065FC039013E0B4F90800FFF797 +:10B0200011FE064603A8CDE90060238A9AB22B469A +:10B03000D4E9001007F022FC012802D0002004B05F +:10B0400070BD0398FBE72DE9F04706460F46904692 +:10B050001C46DDF82090002506E04B464246394666 +:10B060003046FFF78BF86D1CA542F6D3BDE8F0879C +:10B0700070B50346B3F90000B1F90040A04211DBFE +:10B08000B3F90000B1F90440A0420BDCB3F90200AF +:10B09000B1F90240A04205DBB3F90200B1F9064064 +:10B0A000A04201DD002070BD0AB90120FBE7B3F921 +:10B0B0000000B1F900401444A04208DBB3F90000DD +:10B0C000B1F90440A41AA04201DC0120EBE7B3F976 +:10B0D0000200B1F902401444A04208DBB3F90200B7 +:10B0E000B1F90640A41AA04201DC0120DBE7B3F964 +:10B0F0000000B1F900401444A0421CDCB3F9020086 +:10B10000B1F902401444A04215DC18880E88164498 +:10B11000801B05B258884E881644801B04B215FB6C +:10B1200005F014FB040602FB02F0864201DC01205C +:10B13000B9E70020B7E7B3F90000B1F90440A41A59 +:10B14000A0421CDBB3F90200B1F902401444A04252 +:10B1500015DC18888E88B61A801B05B258884E8870 +:10B160001644801B04B215FB05F014FB040602FB19 +:10B1700002F0864201DC012095E7002093E7B3F955 +:10B180000000B1F900401444A0421CDCB3F90200F5 +:10B19000B1F90640A41AA04215DB18880E8816449F +:10B1A000801B05B25888CE88B61A801B04B215FBE6 +:10B1B00005F014FB040602FB02F0864201DC0120CC +:10B1C00071E700206FE7B3F90000B1F90440A41A59 +:10B1D000A0421CDBB3F90200B1F90640A41AA04258 +:10B1E00015DB18888E88B61A801B05B25888CE8861 +:10B1F000B61A801B04B215FB05F014FB040602FB13 +:10B2000002F0864201DC01204DE700204BE700BF41 +:10B21000002048E72DE9F04105460E461C48076826 +:10B220001C480068001D06F039FB50B91948006839 +:10B2300090F82C100120884017490968814316486E +:10B240000160681C38B936B112480168091D1348FD +:10B2500006F06EFB1AE07C190E4800684460BC42A0 +:10B2600007D20C480168091D0D48006806F046FB2E +:10B270000CE008480168091D0A48006806F03EFB1A +:10B2800009480068844201D207480460BDE8F081A3 +:10B2900028000020140000202C0000208C08002032 +:10B2A0001C000020180000204400002010B50446B7 +:10B2B00006F04AFB23480068401C224908602248E7 +:10B2C000006840B9204804600846006801280DD194 +:10B2D00000F0BEF90AE01D48006838B91A48006855 +:10B2E000C06AE16A884201D81748046018480068BB +:10B2F000401C1749086094F82C100120884015491B +:10B300000968084313490860E16A01EB8101124AA8 +:10B3100002EB8100211D06F00BFB06F03FFB0B4802 +:10B32000006868B108480068C06AE16A884207D2CC +:10B330004FF0805009490860BFF34F8FBFF36F8F04 +:10B3400010BD000024000020140000203000002068 +:10B35000400000202C000020B007002004ED00E099 +:10B3600010B516E006F0F0FA0C48C068C468201D5D +:10B3700006F094FA0A480068401E09490860094826 +:10B380000068401E0749086006F008FB204600F0F0 +:10B390005FF8044800680028E4D110BD7808002058 +:10B3A000240000202000002070B504460D46206CCB +:10B3B00070B1216CE0680144E160D4E90210884278 +:10B3C00001D32168E1602846226CE168F4F7BCFFF4 +:10B3D00070BD2DE9F04104460F4615464FF00008B8 +:10B3E000A66B206C48B9206800282CD1A06807F013 +:10B3F00099FB80460020A06025E07DB93946226C8B +:10B400006068F4F7A1FF216C606808446060D4E9CB +:10B410000101884217D32068606014E03946226C2D +:10B42000E068F4F791FF216CE068411AE16021685F +:10B43000E068884203D2216CA068411AE160022DC5 +:10B4400001D106B1761E701CA0634046BDE8F081B4 +:10B4500010B5044694F8510030B9206B06F0BCFAE0 +:10B46000204606F0B9FA1AE094F85100012803D1F9 +:10B47000204606F0B1FA12E094F85100022801D1FA +:10B48000012000E0002050B900BF502080F3118857 +:10B49000BFF34F8FBFF36F8F00BF00BFFEE710BD3C +:10B4A00001464A6A22B10A6B1268C2F1070000E045 +:10B4B0000020704730B54FF47053174800F0070470 +:10B4C0002CB1C01D20F00700134C041B1B1B0246AF +:10B4D000124C22600024114D6C60D018083820F006 +:10B4E00007000F4C206000240D4D2D686C600C4D42 +:10B4F0002D682C601146441A4C60094C24680C607D +:10B50000084D4C682C60084D4C682C604FF000448E +:10B51000064D2C6030BD0000A00800205000002027 +:10B5200058000020600000205C0000206C0000201B +:10B5300000BFFFF715FF064800680128F9D94FF052 +:10B54000805004490860BFF34F8FBFF36F8FF0E75F +:10B55000B007002004ED00E010B5044654B100200F +:10B56000A06020600021E16000231A4619462046B1 +:10B5700006F0F6FD10BD2DE9F04106460D461746D2 +:10B580009846069C0DB9246000E02760E6632564B8 +:10B590000121204606F098FDBDE8F0812DE9FF5F0E +:10B5A00081460E469246DDE90E7B109CAAF1010011 +:10B5B000216B01EB800828F0070808F0070008B9A4 +:10B5C000012000E0002050B900BF502080F3118816 +:10B5D000BFF34F8FBFF36F8F00BF00BFFEE786B191 +:10B5E000002507E0715D04F134004155705D00B93C +:10B5F00002E06D1C102DF5D300BF00214320015542 +:10B6000002E0002084F83400072F00D30627E76209 +:10B6100067640020A064201D06F06DF904F1180095 +:10B6200006F069F92461C7F10700A0616462002097 +:10B63000E06484F8500049464046039A00F018FB45 +:10B640002060BBF1000F01D0CBF80040BDE8FF9FA8 +:10B6500010B5002407E004EB84010F4A02EB8100DF +:10B6600006F03CF9641C072CF5D30C4806F036F9BB +:10B670000B4806F033F90B4806F030F90A4806F09B +:10B680002DF90A4806F02AF90448094908600448D7 +:10B690000849086010BD0000B00700203C080020E9 +:10B6A0005008002064080020780800208C08002042 +:10B6B000180000201C00002010B50146164800E0CC +:10B6C000006803688B42FBD30246436813448B42F5 +:10B6D00004D143684C682344436001460A464B68E2 +:10B6E00013440468A34211D10C4C03682468A3429C +:10B6F00008D04B680468646823444B6003681B6887 +:10B700000B6005E0054B1B680B6001E003680B60F4 +:10B71000884200D0016010BD500000205800002079 +:10B7200070B5054606F010F9A86B08B9012400E0D1 +:10B73000002406F033F9204670BD70B5054606F0CA +:10B7400003F9A86BE96B884201D1012400E00024D1 +:10B7500006F024F9204670BD0A490968096809B94C +:10B76000012100E0002121B14FF0FF31064A1160B4 +:10B7700006E004490968C968C868034A416811605D +:10B780007047000018000020440000200E480068A8 +:10B79000401C08B9012000E0002050B900BF502033 +:10B7A00080F31188BFF34F8FBFF36F8F00BF00BFCF +:10B7B000FEE700BF502080F31188BFF34F8FBFF327 +:10B7C0006F8F00BF00BFFEE77000002070B5044619 +:10B7D00006F0BAF894F9455010E0606A08B9012003 +:10B7E00000E0002038B904F1240007F05BFA18B13A +:10B7F00006F0CEF900E003E0681E45B2002DECDC57 +:10B8000000BFFF2084F8450006F0C8F806F09CF859 +:10B8100094F9445010E0206908B9012000E00020AC +:10B8200048B904F1100007F03DFA08B106F0B0F98C +:10B83000681E45B200E001E0002DECDC00BFFF20F7 +:10B8400084F8440006F0AAF870BD2DE9FC470546CF +:10B85000884691464FF0000A09F1030020F00300EA +:10B8600000F10807E86820B1082F02D007F0004077 +:10B8700010B10020BDE8FC872E1D3468B8F1000F20 +:10B8800025D06A4601A9404600F0B2F808B9002068 +:10B89000F0E718E0206810B1E868A04201D100206C +:10B8A000E8E70198844200D20BE0DDE9001008448B +:10B8B000A04201D80020DDE76068B84200D304E070 +:10B8C00000BF26462468002CE4D100BF0DE008E04C +:10B8D000206810B1E868A04201D10020CAE72646DE +:10B8E000246814B16068B842F2D30CB90020C1E7F3 +:10B8F00014B104F1080000E00020824620683060A6 +:10B9000028686168401A28603A462146284600F0B7 +:10B91000CFF8204600F040F85046ABE72DE9FC4157 +:10B9200004460D4600200190009000260027804626 +:10B930002AE06A4601A9284600F05AF800B920E03A +:10B94000E06818B9019860600021A160E768DDE94E +:10B95000001008440838E0600020E1680860E168F1 +:10B960004860019EE068306000980838706007B158 +:10B970003E6020687168084420602069401C206196 +:10B9800000BF08F101080835686810B12868002870 +:10B99000CFD12069BDE8FC8128B1416841F0004168 +:10B9A0004160014A02607047EFBEADDE70B50546EA +:10B9B0000E4616B1A6F1080000E0002004469CB136 +:10B9C000606800F0004078B1084A206890420BD1CE +:10B9D000606820F000406060286861680844286062 +:10B9E0002146284600F02DF870BD0000EFBEADDE08 +:10B9F00030B503460C461546002100220BB104B1B8 +:10BA00000DB9002030BD0020206028601A685968F8 +:10BA100002F0030038B102F00300C0F10400024458 +:10BA20001868101A091A21F00301102901D2002008 +:10BA3000E8E7102903D3226029600120E2E7002013 +:10BA4000E0E710B5024601B910BD101D00E0006826 +:10BA500010B103688B42FAD300B9F5E74368034499 +:10BA60008B4204D143684C68234443600146036819 +:10BA7000BBB103685B68A3B14B680B440468A34285 +:10BA80000FD10368D468A34202D1D3680B600AE0E7 +:10BA90004B680468646823444B6003681B680B6050 +:10BAA00001E003680B60884200D0016000BFCBE773 +:10BAB0002DE9F04707460C4615464FF0000A60682E +:10BAC00000F00049606820F00048A8EB0500082855 +:10BAD0000ED36619A8EB0500706065603868716860 +:10BAE0000844386031463846FFF7ABFF4FF0010A93 +:10BAF000B9F1000F02D02046FFF74EFF5046BDE8D7 +:10BB0000F08700002DE9F04104464FF0000806F0F0 +:10BB10002BF94948006808B9FFF7CCFC4748006892 +:10BB20002040002870D1D4B1083404F00700B0B12F +:10BB300004F00700C0F10800044404F0070008B94D +:10BB4000012000E0002050B900BF502080F3118890 +:10BB5000BFF34F8FBFF36F8F00BF00BFFEE7002C16 +:10BB600052D03748006884424ED8364E3046056879 +:10BB700001E02E462D686868A04202D2286800289D +:10BB8000F7D12D48006885423ED0306800F10808A2 +:10BB9000286830606868001B102819D92F1907F031 +:10BBA000070008B9012000E0002050B900BF502074 +:10BBB00080F31188BFF34F8FBFF36F8F00BF00BFBB +:10BBC000FEE76868001B78606C603846FFF774FD1C +:10BBD0001B4968680968081A19490860084600681E +:10BBE00019490968884203D2154800681649086057 +:10BBF0001249686809680843686000202860134893 +:10BC00000068401C1149086007F098F808F0070028 +:10BC100008B9012000E0002050B900BF502080F397 +:10BC20001188BFF34F8FBFF36F8F00BF00BFFEE7D8 +:10BC30004046BDE8F0810000580000206C00002064 +:10BC40005C00002050000020600000206400002004 +:10BC50000648006830B10549096801F14800896C5F +:10BC6000491C016001480068704700001400002072 +:10BC7000001F4FF080730360001F21F00103036079 +:10BC8000001F054B036014380260001F6FF00203B1 +:10BC900003602038704700008DB700083EB50024CF +:10BCA000002000F035F884B245F2500084422CD0D8 +:10BCB000401C844229D01920ADF8040001208DF8E1 +:10BCC00006008DF807009DF807209DF80610BDF8C6 +:10BCD000043003F5FA6398B2FEF7C0FC8DF8080053 +:10BCE00000208DF800008DF801008DF80200002181 +:10BCF000009800F037F8DDE9010100F013F845F293 +:10BD00005101002000F07AF800BF01203EBD000084 +:10BD100001460022024800EB8102106870470000D3 +:10BD20005028004003B581B09DF806008DF8010051 +:10BD30009DF807008DF80200BDF80400C0B28DF830 +:10BD400003009DF808008DF80000002269460448B1 +:10BD5000F7F7ECF808B901200EBD0020FCE7000061 +:10BD6000A804002013B586B00C469DF818008DF885 +:10BD700004009DF819008DF805009DF81A008DF853 +:10BD800006008DF80740002004900590002201A9CC +:10BD90000448F7F72BF910B9012008B010BD0020B6 +:10BDA000FBE70000A804002000B587B0002201A92D +:10BDB0001048F7F71DF8002206A90E48F6F7F2FF23 +:10BDC0009DF804000C4988729DF805100A48C1725C +:10BDD0009DF8061001739DF8181001729DF8191056 +:10BDE00081719DF81A10C1719DF81B00024988806D +:10BDF00007B000BDA8040020A044002070B5044690 +:10BE00000D46F6F737FB2A4621460248F6F7C0FFF3 +:10BE100070BD0000A804002010B588B06946044831 +:10BE2000F7F7C2FA04460CB108B010BD00BFFBE73B +:10BE30009457002010B50E480E4908600020486055 +:10BE400000210C488160C160016141610421816170 +:10BE5000F7F7CFFA08B1F4F74DFF4FF4006105484A +:10BE6000F7F758F908B1F4F745FFFFF7D5FF10BD14 +:10BE7000002C0140945700200949496829B108491C +:10BE8000496848600649486002E005490860486022 +:10BE900000214160416A21F0804141627047000009 +:10BEA0003C02002010B5282002F08EFC04462CB97C +:10BEB00005A10DA002F02CFA002010BD204600F0D4 +:10BEC00045F82046F9E7000073676C5F616E696DA5 +:10BED0005F6372656174653A206D616C6C6F63209D +:10BEE0006661696C656400001B5B33316D5B4552B4 +:10BEF000524F525D0000000010B5044600BF24B947 +:10BF0000B222084908A000F02DFB00BF606AC0F310 +:10BF1000807010B9204600F0DDF8204601F05EFF89 +:10BF200010BD0000033401082E2E5C557365725C51 +:10BF300073797374656D5C73676C5C636F72655C59 +:10BF400073676C5F616E696D2E6300000021416054 +:10BF500001608160C160016141618161C161016213 +:10BF6000416A21F000414162416A21F0804101F1C2 +:10BF70008041416270472DE9FF5F81468A46144641 +:10BF80009B46BAF1000F01D0D14503D3584604B007 +:10BF9000BDE8F09FB9F1000F01D12046F7E700207E +:10BFA000000440EA19404FEA094152460023CDE916 +:10BFB000001008460199F4F796F988460746ABEB5E +:10BFC0000405EE17A5FB070106FB071105FB081189 +:10BFD000000C40EA0140001902900298D7E70000E7 +:10BFE00070B5054600BF25B96D22134913A000F0B6 +:10BFF000B9FA00BF00241A480068A84208D11849BD +:10C00000686808600846006808B90020486070BD8C +:10C010001348046800E0646814B16068A842FAD16B +:10C0200004B9F4E7686860600D484068A84201D12F +:10C030000B48446000BFEAE7D63301082E2E5C555A +:10C040007365725C73797374656D5C73676C5C6344 +:10C050006F72655C73676C5F616E696D2E63000063 +:10C060003C02002070B504460D4600BF24B9902262 +:10C070000D490EA000F076FA00BF606AC0F3807030 +:10C0800038B135B12046FFF7F7FE606A20F08040F6 +:10C09000606200BF0E48D0F8BC00A060606A65F323 +:10C0A0001D00606270BD0000E63301082E2E5C5555 +:10C0B0007365725C73797374656D5C73676C5C63D4 +:10C0C0006F72655C73676C5F616E696D2E630000F3 +:10C0D0004C28012010B5044600BF24B9A2220A4909 +:10C0E0000AA000F03FFA00BF606AC0F3807040B958 +:10C0F0002046FFF775FF606A20F0804000F1804025 +:10C1000060620020A06010BDF53301082E2E5C5542 +:10C110007365725C73797374656D5C73676C5C6373 +:10C120006F72655C73676C5F616E696D2E63000092 +:10C130002DE9F0474FF0000800250026304804683C +:10C14000A94659E000BF2F48D0F8BC000646A068B9 +:10C15000B04200D950E0A068351A00BFA06920B9EC +:10C16000D022294929A000F0FDF900BF00BFE069F5 +:10C1700020B9D122244925A000F0F4F900BFD4E968 +:10C180000423E168A94201D9AC4601E0D4F80CC00F +:10C190006046E769B847804641462046A269904715 +:10C1A000E068A84226D2606A20F040406FF040412B +:10C1B000884205D0606A401E616A60F31D016162B9 +:10C1C000206A10B12046216A8847606A20F040400A +:10C1D00060B92046FFF77EFF606AC00F30B1D4F827 +:10C1E0000490204601F0FAFD4C4605E0D4E9020136 +:10C1F0000844A060646800BF002CA3D1BDE8F087AC +:10C200003C0200204C280120133401082E2E5C55DE +:10C210007365725C73797374656D5C73676C5C6372 +:10C220006F72655C73676C5F616E696D2E63000091 +:10C2300070B504460D46164600BF0CB105B12EB9C7 +:10C2400040F20132284929A000F08CF900BFB5F96D +:10C250000200B4F90610884211DCB5F90600B4F901 +:10C26000021088420BDBB5F90000B4F904108842D3 +:10C2700005DCB5F90400B4F90010884201DA0020A9 +:10C2800070BDB4F90000B5F90010884202DDB4F9C0 +:10C29000000001E0B5F900003080B4F90400B5F900 +:10C2A0000410884202DAB4F9040001E0B5F9040090 +:10C2B000B080B4F90200B5F90210884202DDB4F989 +:10C2C000020001E0B5F902007080B4F90600B5F98A +:10C2D0000610884202DAB4F9060001E0B5F906005A +:10C2E000F0800120CCE700009A3201082E2E5C5528 +:10C2F0007365725C73797374656D5C73676C5C6392 +:10C300006F72655C73676C5F636F72652E630000AC +:10C3100010B50246B2F90000B1F90030984202DAD5 +:10C32000B2F9000001E0B1F90000B2F900301B1AC7 +:10C33000B2F90400B1F90440A04202DDB2F90400F0 +:10C3400001E0B1F90400B2F90440001B0344B2F962 +:10C350000200B1F90240A04202DAB2F9020001E0A3 +:10C36000B1F90200B2F90240201A0344B2F9060002 +:10C37000B1F90640A04202DDB2F9060001E0B1F9D0 +:10C380000600B2F90640001B184410BD10B5044663 +:10C3900000BF2CB940F22E72064907A000F0E2F867 +:10C3A00000BF4FF40050608020804042E080A080B9 +:10C3B00010BD00005B3101082E2E5C557365725C68 +:10C3C00073797374656D5C73676C5C696E636C75AF +:10C3D00064655C73676C5F636F72652E6800000054 +:10C3E00070B504460D4600BF04B12DB94FF4467236 +:10C3F000284929A000F0B6F800BFB5F90200B4F949 +:10C400000610884211DCB5F90600B4F90210884222 +:10C410000BDBB5F90000B4F90410884205DCB5F96E +:10C420000400B4F90010884201DA002070BDB4F9AC +:10C430000000B5F90010884202DDB4F9000001E007 +:10C44000B5F900002080B4F90400B5F90410884261 +:10C4500002DAB4F9040001E0B5F90400A080B4F9EF +:10C460000200B5F90210884202DDB4F9020001E0D1 +:10C47000B5F902006080B4F90600B5F906108842EB +:10C4800002DAB4F9060001E0B5F90600E080012007 +:10C49000CCE70000A83201082E2E5C557365725C53 +:10C4A00073797374656D5C73676C5C636F72655CE4 +:10C4B00073676C5F636F72652E63000070B504462E +:10C4C0000D4600BF04B12DB940F2AD721A491BA050 +:10C4D00000F048F800BFB4F90000B5F90010884238 +:10C4E00002DAB4F9000001E0B5F900002080B4F9E7 +:10C4F0000400B5F90410884202DDB4F9040001E03B +:10C50000B5F90400A080B4F90200B5F90210884220 +:10C5100002DAB4F9020001E0B5F902006080B4F972 +:10C520000600B5F90610884202DDB4F9060001E004 +:10C53000B5F90600E08070BD7D3101082E2E5C55F6 +:10C540007365725C73797374656D5C73676C5C6939 +:10C550006E636C7564655C73676C5F636F72652E88 +:10C560006800000008B504460D4616462B462246D4 +:10C5700003A10CA0009601F0CBFE00BFFEE7000077 +:10C5800066696C653A2025732C2066756E63746944 +:10C590006F6E3A2025732C206C696E653A202564F5 +:10C5A000000000001B5B33366D5B41535345525412 +:10C5B0005D0000002DE9F041002002F0BFF80646C2 +:10C5C00035465848B0F91000032190FBF1F007B24E +:10C5D0005448B0F9120090FBF1F00FFA80F800BF58 +:10C5E00000BF2DB940F2EF524F4950A0FFF7BAFFFC +:10C5F00000BF28893844401E01B2A981688940449F +:10C60000401E01B2E981284602F060FE00BF002111 +:10C61000304602F095FE0021304602F0F9FEFFF7A9 +:10C6200041FC04462546374600BF00BF25B9B52268 +:10C63000484949A0FFF796FF00BF2F6000BF25467D +:10C640004FF47A7700BF00BF25B9F8224C4942A0C9 +:10C65000FFF788FF00BFEF6000BF2546FF2700BF40 +:10C6600000BF25B9D12247493BA0FFF77BFF00BFA0 +:10C670002F6100BF2546002700BF00BF25B9DE227D +:10C68000414935A0FFF76EFF00BF6F6100BF25462F +:10C690003E4FDFF8FC8000BF00BF1DB117B1B8F1FD +:10C6A000000F04D1C3223B492BA0FFF75BFF00BF63 +:10C6B000AF61C5F81C8000BF01212046FFF7D2FC06 +:10C6C00018E000BF00BF1748D0F8BC0000BF1549F4 +:10C6D000D1F8B810401A0A2800D20AE000BF114869 +:10C6E000D0F8BC000F49C1F8B80000BF03F068F9EA +:10C6F00000BF00BF254600BF00BF2DB940F2111298 +:10C70000254915A0FFF72EFF00BF686AC0F38070AF +:10C710000028D6D02046FFF7EFFB304602F0F0F9B4 +:10C72000BDE8F0814C280120AE3901082E2E5C5561 +:10C730007365725C73797374656D5C73676C5C6947 +:10C740006E636C7564655C73676C5F636F72652E96 +:10C7500068000000FD3901082E2E5C557365725C7F +:10C7600073797374656D5C73676C5C696E636C750B +:10C7700064655C73676C5F616E696D2E68000000B4 +:10C78000513A0108213A01083A3A010885E30008C4 +:10C7900077BF00080F3A01086B3A010837B581B03E +:10C7A000101DC208BDF8080040EA00400B4D00EA29 +:10C7B0000501BDF8040040EA004000EA0503581AEC +:10C7C000504301EB501000EA050444EA144080B2E3 +:10C7D0000090BDF80050284604B030BD1FF8E007B7 +:10C7E00037B581B0101DC208BDF8080040EA00400E +:10C7F0000B4D00EA0501BDF8040040EA004000EAE4 +:10C800000503581A504301EB501000EA050444EAAE +:10C81000144080B20090BDF80050284604B030BDEE +:10C820001FF8E00770B594B00446002528466D1C3B +:10C8300004A941F82040BBE000BF102D05DB40F209 +:10C84000AA525E495EA0FFF78DFE00BF681E054636 +:10C8500004A951F82040606A20B128466D1C626A24 +:10C8600041F82020204602F03DFB00B1A0E0264622 +:10C8700000BF00BF2EB94FF482625A495A48FFF7F1 +:10C8800071FE00BF96F8280000F00100E0B12046DC +:10C8900000F0BAF8554B0FCB8DE80F0000BFA06930 +:10C8A00028B940F2C152454945A0FFF75BFE00BFE1 +:10C8B0006A4621460020A3699847204602F0C4FB3F +:10C8C000204602F06DF973E0264600BF00BF2EB986 +:10C8D00040F2564246494448FFF744FE00BF96F8EE +:10C8E0002800C0F3C00000282BD0404B1033D3E900 +:10C8F0000020D3E90213CDE90213CDE9002000BFE7 +:10C90000A06928B940F2D5522C492DA0FFF72AFE84 +:10C9100000BF6A4621460020A3699847264600BF0B +:10C9200000BF2EB940F2624232492F48FFF71AFE8B +:10C9300000BF96F8280020F0080086F8280000BF05 +:10C9400000BF264600BF00BF2EB940F23E422A4932 +:10C950002548FFF707FE00BF96F82800C0F3400007 +:10C96000E8B1204600F050F8E16902A802F064F94D +:10C97000224604F1080102A8FFF75AFC80F00100EA +:10C9800030B12046FFF702FD204602F03BF80FE0F1 +:10C99000204600F039F8204602F034F800BF206A43 +:10C9A00028B128466D1C04A9226A41F8202000BF46 +:10C9B000002D3FF741AF14B070BD00008D3301086A +:10C9C0002E2E5C557365725C73797374656D5C7340 +:10C9D000676C5C636F72655C73676C5F636F7265D5 +:10C9E0002E630000BC30010878EB0008A833010872 +:10C9F000083101081C310108F73001080021014805 +:10CA0000018670474C2801202DE9F041044600BF03 +:10CA10002CB94FF45572324932A0FFF7A3FD00BF85 +:10CA20004FF0FF376FF000487E08B4F90000B4F90A +:10CA30000410884205DCB4F90200B4F906108842FB +:10CA400001DDBDE8F0813048008E38B92E482168FC +:10CA500041636168816301210186F2E7002517E0E7 +:10CA60002949343101EBC500214601F0D7FE68B1F8 +:10CA70002549343101EBC5002146FFF749FC064644 +:10CA800006B9DEE7464501DAB0462F46681CC5B256 +:10CA90001D48008EA842E3DC002F07DB1A49343121 +:10CAA00001EBC7002146FFF709FDCAE71648008ED3 +:10CAB00010280EDA1448018E008E401C82B21248F3 +:10CAC0000286343000EBC10021680160616841607A +:10CAD00004E021460C48AC30FFF7F0FC00BFB0E7A3 +:10CAE000BA3201082E2E5C557365725C73797374CB +:10CAF000656D5C73676C5C636F72655C73676C5FBC +:10CB0000636F72652E6300004C2801202DE9FF4FF2 +:10CB100091B005461E9F219C07EB4701606800EB22 +:10CB2000810090F90B006189081AB4F91410401AB9 +:10CB3000109007EB4701606850F82100216800EB76 +:10CB4000010807EB4701606800EB8100007A0F9055 +:10CB500007EB4701606800EB810080790E900020B0 +:10CB60000D900A900890824607EB4701606800EB41 +:10CB7000810090F90A101398084400B2ADF8100033 +:10CB80001099149801440E98081A00B2ADF81200DA +:10CB900007EB4701606800EB810090F90A101398D9 +:10CBA00001440F980844401E00B2ADF814001099DB +:10CBB00014980844401E00B2ADF816000DF1100B99 +:10CBC00006A8039059462846039AFFF731FB10B98F +:10CBD00015B0BDE8F08F06A81299FFF701FC00B967 +:10CBE000F6E7BDF818202B88D21A10B2BDF81A202B +:10CBF0006B88D21A11B22B8A01FB0303AA6802EBDD +:10CC000043020892BDF91AB07AE0DDF820A0BDF920 +:10CC10001200ABEB00000B90BDF91800039063E02D +:10CC2000BDF910100398401A0C900F9ADDE90B1013 +:10CC300001FB0206A07D042810D1C6F34F0906F0BF +:10CC4000010020B118F8090000F00F0002E018F808 +:10CC5000090000112D49085C0A9029E0A07D0228F6 +:10CC600011D1C6F38F0906F00300C0F103004000A4 +:10CC70000D9018F809000D99084100F003002449AF +:10CC8000085C0A9014E0A07D012811D1C6F3CF09F9 +:10CC900006F00700C0F107000D9018F809000D9983 +:10CCA000084100F0010008B1FF2000E000200A90D8 +:10CCB0000A98C2B2BAF80000014602901F98FFF726 +:10CCC0008FFD0990BAF8000001900146209A09985A +:10CCD000FFF786FD0290BDF80800AAF800000AF1EF +:10CCE000020A0398401C0390BDF91C10039881426E +:10CCF00096DA298A089800EB410008900BF1010BA5 +:10CD0000BDF91E00584580DA00BF61E78030010898 +:10CD1000903001082DE9FF4F91B0824617461D461D +:10CD2000DDF87C804FF0000B002400200E90B7F956 +:10CD3000000028440D90B7F90400401B0C90B7F98F +:10CD4000020028440B90B7F90600401B0A9000200F +:10CD5000099008900FAA5046129902F001FE10B9EE +:10CD600015B0BDE8F08F39460FA8FFF739FB00B9C1 +:10CD7000F6E700200790069005FB05F00590681C7B +:10CD800040430490BDF83E00BAF80230C01A02B227 +:10CD9000BDF83C00BAF80030C01A01B2504602F0AB +:10CDA000E9FD83464DBBBDF93E6021E05C46BDF91F +:10CDB0003C9014E0B8F1FF0F03D1BDF8780020805B +:10CDC0000AE020884246014602901E98FFF7E6FCE2 +:10CDD0000390BDF80C00208009F10109A41CBDF9E5 +:10CDE00040004845E6DABAF810000BEB400B761C21 +:10CDF000BDF94200B042D9DAB1E0BDF93E90A9E0F8 +:10CE00005C460B9881451EDD0A9881451BDABDF909 +:10CE10003C6013E0B8F1FF0F03D1BDF8780020802B +:10CE20000AE020884246014602901E98FFF7B6FCB1 +:10CE30000390BDF80C002080761CA41CBDF94000B6 +:10CE4000B042E7DA80E00B98814501DD0A9800E006 +:10CE50000B9808900898A9EB000040430790BDF993 +:10CE60003C606DE00D98864215DD0C98864212DA22 +:10CE7000B8F1FF0F03D1BDF8780020805DE0208875 +:10CE80004246014602901E98FFF788FC0390BDF8C9 +:10CE90000C00208051E00D98864201DD0C9800E0E6 +:10CEA0000D9809900998311A321A079801FB02006F +:10CEB000069004990698884200DB3FE0DDE9051002 +:10CEC000884228DB069802F0CFFCC0F1FF000E90EC +:10CED000B8F1FF0F0BD12088009001460E9A1E98E2 +:10CEE000FFF75CFC0190BDF80400208025E020885D +:10CEF000009001460E9A1E98FFF750FC0390208880 +:10CF00004246014600900398FFF748FC0290BDF8A6 +:10CF10000800208011E0B8F1FF0F03D1BDF87800C0 +:10CF200020800AE020884246014602901E98FFF7C2 +:10CF300035FC0390BDF80C00208000BF761CA41CBB +:10CF4000BDF94000B0428DDABAF810000BEB400B8F +:10CF500009F10109BDF942004845BFF651AF00BFD4 +:10CF6000FEE62DE9FF4F97B0834615461F46DDF8D4 +:10CF700094A000201490002400261390B5F900001E +:10CF800038441290B5F90400C01B1190B5F90200A5 +:10CF900038441090B5F90600C01B0F9000200E9089 +:10CFA0000D9015AA5846189902F0DAFC10B91BB07A +:10CFB000BDE8F08F294615A8FFF712FA00B9F6E789 +:10CFC00000200C900B9007FB07F00A90781C404360 +:10CFD0000990B5F90400B5F90010401A401C2499D5 +:10CFE0000988C904490A91FBF0F00890B5F90600D8 +:10CFF000B5F90210401A401C24990968C1F34C315C +:10D00000890291FBF0F00790002006900590BDF892 +:10D010005600BBF80230C01A02B2BDF85400BBF88B +:10D020000030C01A01B2584602F0A4FC1490002F40 +:10D0300044D1BDF956803CE0149CB5F90200A8EB40 +:10D04000000007994843800A0590BDF9549024E0F8 +:10D05000B5F90000A9EB000008994843800A069042 +:10D06000059802B2069801B2249802F0F7FA064633 +:10D07000BAF1FF0F02D1308820800BE020880390A6 +:10D080003088524602900399FFF788FB0490BDF860 +:10D090001000208009F10109A41CBDF95800484581 +:10D0A000D6DABBF81010149800EB4100149008F188 +:10D0B0000108BDF95A004045BEDAE2E0BDF95690DC +:10D0C000DAE0149CB5F90200A9EB00000799484387 +:10D0D000800A0590109881452FDD0F9881452CDA44 +:10D0E000BDF9548024E0B5F90000A8EB00000899D0 +:10D0F0004843800A0690059802B2069801B2249827 +:10D1000002F0ACFA0646BAF1FF0F02D13088208057 +:10D110000BE0208803903088524602900399FFF775 +:10D120003DFB0490BDF81000208008F10108A41C0C +:10D13000BDF958004045D6DA96E01098814501DDEA +:10D140000F9800E010980D900D98A9EB0000404357 +:10D150000C90BDF9548082E0B5F90000A8EB000006 +:10D1600008994843800A0690059802B2069801B2D1 +:10D17000249802F073FA06461298804515DD11983E +:10D18000804512DABAF1FF0F02D13088208062E0C8 +:10D19000208803903088524602900399FFF7FEFAE8 +:10D1A0000490BDF81000208055E01298804501DD04 +:10D1B000119800E012980E900E98A8EB0001A8EBD1 +:10D1C00000020C9801FB02000B9009990B98884211 +:10D1D00000DB41E0DDE90A1088422ADB0B9802F00F +:10D1E00043FBC0F1FF001390BAF1FF0F0CD1208870 +:10D1F000019030880090139A0199FFF7CFFA0290BE +:10D20000BDF80800208026E020880190308800903A +:10D21000139A0199FFF7C2FA0490208852460146FA +:10D2200001900498FFF7BAFA0390BDF80C00208033 +:10D2300011E0BAF1FF0F02D1308820800BE0208886 +:10D2400003903088524602900399FFF7A7FA0490A2 +:10D25000BDF81000208000BF08F10108A41CBDF932 +:10D2600058004045BFF678AFBBF81010149800EB9B +:10D270004100149009F10109BDF95A004845BFF673 +:10D2800020AF00BF93E62DE9FF4F99B016461F4629 +:10D29000DDE928A5A7EB0A00401C002803DDA7EB69 +:10D2A0000A00401C00E000201890002017908346E0 +:10D2B00018984043169007FB07F015900020149033 +:10D2C00000241390B6F9000038441290B6F9040017 +:10D2D000C01B1190B6F9020038441090B6F9060050 +:10D2E000C01B0F90B6F9000050440E90B6F9040030 +:10D2F000A0EB0A000D90B6F9020050440C90B6F96C +:10D300000600A0EB0A000B9000200A9009901898E4 +:10D31000401E40430890781C4043079005AADDE971 +:10D32000190102F01DFB10B91DB0BDE8F08F3146A8 +:10D3300005A8FFF755F800B9F6E7BDF816301998BB +:10D340004088181A02B2BDF8143019980088181ACB +:10D3500001B2199802F00EFB1490002F49D1BDF9CB +:10D36000168041E0149CBDF9149031E00E9881457F +:10D370001ADB0D98814517DC0C98804514DB0B985F +:10D38000804511DCFF2D03D1BDF8980020801CE002 +:10D3900020882A46014603902698FFF7FFF904905B +:10D3A000BDF81000208010E0FF2D03D1BDF89C00D7 +:10D3B00020800AE020882A46014603902798FFF73C +:10D3C000EDF90490BDF81000208009F10109A41CBA +:10D3D000BDF918004845C9DA1999098A149800EB73 +:10D3E0004100149008F10108BDF91A004045B9DA6E +:10D3F0001BE1BDF9168013E1149C1098804536DDC1 +:10D400000F98804533DABDF914902BE00E988145D2 +:10D4100002DB0D98814511DDFF2D03D1BDF89C0085 +:10D4200020801CE020882A46014603902798FFF7B9 +:10D43000B5F90490BDF81000208010E0FF2D03D155 +:10D44000BDF8980020800AE020882A460146039013 +:10D450002698FFF7A3F90490BDF81000208009F189 +:10D460000109A41CBDF918004845CFDAD0E0109896 +:10D47000804501DD0F9800E0109809900998A8EB0D +:10D48000000040431790BDF91490BCE0129881450C +:10D490002CDB1198814529DC0C98804502DB0B9828 +:10D4A000804511DDFF2D03D1BDF89C002080A6E052 +:10D4B00020882A46014603902798FFF76FF90490C9 +:10D4C000BDF8100020809AE0FF2D03D1BDF8980030 +:10D4D000208094E020882A46014603902698FFF792 +:10D4E0005DF90490BDF81000208088E01298814515 +:10D4F00001DD119800E012980A900A98A9EB00014A +:10D50000A9EB0002179801FB020B0798834500DB8B +:10D5100076E00898834511DAFF2D03D1BDF8980015 +:10D5200020800AE020882A46014603902698FFF7CB +:10D5300035F90490BDF81000208061E0169883450D +:10D5400021DA584602F090F91390FF2D09D1139A71 +:10D55000DDE92610FFF722F90290BDF808002080CF +:10D560004DE0139ADDE92610FFF718F904902088A2 +:10D570002A46014601900498FFF710F90390BDF880 +:10D580000C0020803BE01598834527DD584602F0CB +:10D590006BF9C0F1FF001390FF2D0BD12088019093 +:10D5A0000146139A2798FFF7F9F80290BDF8080092 +:10D5B000208024E0208801900146139A2798FFF7E5 +:10D5C000EDF8049020882A46014601900498FFF760 +:10D5D000E5F80390BDF80C00208010E0FF2D03D18A +:10D5E000BDF89C0020800AE020882A46014603906E +:10D5F0002798FFF7D3F80490BDF81000208000BFF3 +:10D6000009F10109A41CBDF918004845BFF63EAF59 +:10D610001999098A149800EB4100149008F1010847 +:10D62000BDF91A004045BFF6E7AE00BF7CE62DE924 +:10D63000F04F85B08046894617469A46DDE910B519 +:10D640000E9C002004901FE004A9204602F0CAF9B5 +:10D6500004442846049902F0B1F80646CDE902B523 +:10D66000BDF83C00ADF8040053463A4649464046F2 +:10D670000096FFF74BFA06EB4601686800EB810065 +:10D68000808807EB201007B220780028DCD105B095 +:10D69000BDE8F08F2DE9FE43064606F11404D6F8E6 +:10D6A000B090002500279EE006F1300000EBC70592 +:10D6B000656100BFADB1B5F90000002811DBB5F917 +:10D6C000020000280DDB4C48B0F91000B5F9041039 +:10D6D000884206DD4848B0F91200B5F906108842C4 +:10D6E00005DC40F20D62454945A0FEF73BFF00BF57 +:10D6F0004FF00008E8886988401A401C608228883A +:10D70000208068886080A888A080A0882188401A2E +:10D71000401C2082218AE068B0FBF1F1B5F90600D7 +:10D72000B5F90220801A401C814204D2218AE068A7 +:10D73000B0FBF1F005E0B5F90600B5F90210401AAA +:10D74000401C6082B5F90600B5F90410B5F9022055 +:10D75000CDE900210290B5F9003096F82E2031A1D4 +:10D760003FA000F0D5FD37E0B5F90600B4F902108E +:10D77000401A401C618A884206DAB5F90600B4F9FD +:10D780000210401A401C00E0608A1FFA80F860888E +:10D790004044401E00B2E08000BF00BF96F82F005A +:10D7A000154991F8322001219140084008B9012023 +:10D7B00000E000200028F0D12E3670783178C1F1D9 +:10D7C0000201084070702E3E21464846FCF7D6FE06 +:10D7D0006088404400B26080B4F90200B5F90610D8 +:10D7E0008842C1DD7F1CB08DB8423FF75DAF00209D +:10D7F000B085BDE8FE8300004C280120C833010835 +:10D800002E2E5C557365725C73797374656D5C73F1 +:10D81000676C5C636F72655C73676C5F636F726586 +:10D820002E6300005B66623A25645D73676C5F641B +:10D830007261775F7461736B3A20646972747920E6 +:10D8400061726561202078313A25642079313A256A +:10D85000642078323A25642079323A256400000049 +:10D860001B5B33346D5B54524143455D0000000047 +:10D8700000210348A0F80A11A0F808110020704701 +:10D88000105101201FB500BF134991F80811491C20 +:10D8900001F00F001049B1F80A11814201D10121B4 +:10D8A00000E0002121B10DA118A000F031FD1FBD45 +:10D8B0000948B0F80811083000EB01109DE81E007F +:10D8C0001EC0054890F80801401C00F00F010248F6 +:10D8D000A0F8081100BFEAE7105101204576656EF7 +:10D8E000742071756575652069732066756C6C2C84 +:10D8F000206D617962652073797374656D20697339 +:10D9000020746F6F20736C6F770000001B5B3331E6 +:10D910006D5B4552524F525D000000007FB5002400 +:10D92000ADE0009C6CB9BDF80C00062804D002A83C +:10D93000FCF774FD044604E064480468684600F09F +:10D940000FFB002C7ED0BDF90810B4F90C00814209 +:10D9500002DABDF9080001E0B4F90C00B4F90810CE +:10D96000884202DAB4F908000AE0BDF90810B4F9F7 +:10D970000C00814202DABDF9080001E0B4F90C00A4 +:10D98000ADF80800BDF90A10B4F90E00814202DAC0 +:10D99000BDF90A0001E0B4F90E00B4F90A1088429A +:10D9A00002DAB4F90A000AE0BDF90A10B4F90E006F +:10D9B000814202DABDF90A0001E0B4F90E00ADF8C7 +:10D9C0000A00BDF80C0002280DD194F82A00C0F31B +:10D9D000800000B153E0608D20F00400001D6085E0 +:10D9E0003A4804601EE0BDF80C0003281AD194F8F0 +:10D9F0002A00C0F3800070B93448006850B1334841 +:10DA00000068A04206D03148006800909DE80F00F1 +:10DA1000FFF738FF33E0608D20F0040060850020C0 +:10DA20002A49086000BFA06928B94FF4AA722849A2 +:10DA300028A0FEF797FD00BF6069019000946A4638 +:10DA4000214600E008E00020A36998472069A8B1BA +:10DA500068462169884711E027A134A000F058FCEE +:10DA6000BDF80C00032809D11848006830B11748E8 +:10DA7000006800909DE80F00FFF704FF00BF6846B4 +:10DA800000BF1249B1F80821B1F80A118A4201D148 +:10DA9000012100E0002111B14FF0FF3112E00B49EC +:10DAA000B1F80A21083101EB02152ECD80E82E00D5 +:10DAB000064991F80A11491C01F00F020349A1F827 +:10DAC0000A21002100293FF42CAF7FBD1051012015 +:10DAD000823401082E2E5C557365725C7379737401 +:10DAE000656D5C73676C5C636F72655C73676C5FBC +:10DAF0006576656E742E6300706F73206973206F96 +:10DB00007574206F66206F626A656374206F72207F +:10DB10006E6F206576656E745F6C6F73742C207306 +:10DB20006B6970206576656E740000001B5B333492 +:10DB30006D5B54524143455D0000000010B5044642 +:10DB40000CB9012000E0002040B13E23324A33A14D +:10DB50003CA000F0DDFB4FF0FF3010BD206868B93D +:10DB60003CA138A000F0D4FB00BF42222A4943A0C8 +:10DB7000FEF7F8FC00BF4FF0FF30EEE7206968B910 +:10DB800047A130A000F0C4FB00BF482222493BA0BF +:10DB9000FEF7E8FC00BF4FF0FF30DEE7A06868B991 +:10DBA00048A128A000F0B4FB00BF4E221A4933A0C0 +:10DBB000FEF7D8FC00BF4FF0FF30CEE7142221461D +:10DBC0004B48F2F7C1FB4A48001F2168016200215F +:10DBD00001834183A089401E01B24548001F818313 +:10DBE000E089401E01B24248001FC183A168416222 +:10DBF000A08981B23E48001F018500203C49091FD1 +:10DC0000C1F8BC0003213A48001F80F833100021FE +:10DC100080F832100020A0E7A431010846756E6339 +:10DC200074696F6E3A2025732C204C696E653A201A +:10DC300025642C206662696E666F206973204E55DC +:10DC40004C4C00001B5B33316D5B4552524F525DB3 +:10DC500000000000596F7520686176656E2774209A +:10DC600073657420757020746865206672616D65D7 +:10DC7000206275666665722E000000002E2E5C55CF +:10DC80007365725C73797374656D5C73676C5C63E8 +:10DC90006F72655C73676C5F636F72652E63000003 +:10DCA000596F7520686176656E27742073657420DE +:10DCB00075702074686520666C7573682061726584 +:10DCC000612E0000596F7520686176656E2774209B +:10DCD00073657420757020746865206672616D6567 +:10DCE000206275666665722073697A652E00000091 +:10DCF000502801202DE9FC4104460D46E08880B201 +:10DD0000CDE90005A788BBB26788BAB22788B9B247 +:10DD1000124F38693F697E6FB04700BF104890F8D6 +:10DD200033000F4991F83220012191400843C1B2DC +:10DD30000B4880F83310806860B1094890F83200D1 +:10DD400080F00101064880F83210001D50F82110C3 +:10DD5000001F016200BFBDE8FC810000A04400205C +:10DD60004C280120F8B505460C4600BF2CB940F2FE +:10DD70005142104910A0FEF7F5FB00BF002600201D +:10DD80000090002711E06946284601F02BFE05446B +:10DD90002046009901F012FD074607EB4701606835 +:10DDA00000EB8100808806EB201628780028EAD155 +:10DDB0003046F8BD003301082E2E5C557365725C49 +:10DDC00073797374656D5C73676C5C636F72655CAB +:10DDD00073676C5F636F72652E63000010B5044655 +:10DDE0002046FCF7C5FE04498968081A0249886084 +:10DDF0002046FCF7A5FE10BD1C520120F8B50446D4 +:10DE00000D46164600BF04B12DB94FF492624A493F +:10DE10004AA0FEF7A7FB00BF00200090092E74D295 +:10DE2000DFE806F0051C2B313B4D57647400B4F954 +:10DE30000010B5F90020881A00EBD071491009B222 +:10DE4000ADF80010B4F90210B5F90220881A00EB01 +:10DE5000D071491009B2ADF802106AE0B4F90010AF +:10DE6000B5F90020881A00EBD071491009B2ADF85D +:10DE700000100020ADF802005BE00020ADF80000CB +:10DE8000ADF8020055E020882988401A00B2ADF8AC +:10DE900000000020ADF802004BE0B4F90010B5F925 +:10DEA0000020881A00EBD071491009B2ADF80010BB +:10DEB00060886988401A00B2ADF8020039E000209D +:10DEC000ADF8000060886988401A00B2ADF8020021 +:10DED0002FE020882988401A00B2ADF80000608841 +:10DEE0006988401A00B2ADF8020022E00020ADF8C7 +:10DEF0000000B4F90210B5F90220881A00EBD071C5 +:10DF0000491009B2ADF8021013E011E02088298809 +:10DF1000401A00B2ADF80000B4F90210B5F90220C1 +:10DF2000881A00EBD071491009B2ADF8021000E078 +:10DF300000BF00BF0098F8BD1A3301082E2E5C55B3 +:10DF40007365725C73797374656D5C73676C5C6325 +:10DF50006F72655C73676C5F636F72652E63000040 +:10DF600010B50389164CA4881B1B19B24489144BA5 +:10DF7000DB88E31A1AB2002901DD0B4600E04B42B0 +:10DF8000002A01DD144600E05442A3420ADD0029C4 +:10DF900003DD0A238381C1810EE0092383814B4283 +:10DFA000C38109E0002A03DD08238381C28103E0E5 +:10DFB000072383815342C381014B84685C6010BD99 +:10DFC000105101202DE9FE4304460D4617469846A0 +:10DFD000DDF8289000BF04B12DB940F2D2422149AA +:10DFE00021A0FEF7BFFA00BF00200290A088218880 +:10DFF000401A401C00B2ADF80400E0886188401A65 +:10E00000401C00B2ADF8060029463846FFF7AAFECC +:10E01000404400B2ADF800002E4600BF00BF2EB94C +:10E0200040F2E27219491A48FEF79CFA00BF708963 +:10E0300000B2ADF802004A46694601A8FFF7DEFECD +:10E040000290BDF808002188084400B2ADF808002D +:10E05000BDF80A006188084400B2ADF80A000298D1 +:10E06000BDE8FE832C3301082E2E5C557365725C6F +:10E0700073797374656D5C73676C5C636F72655CF8 +:10E0800073676C5F636F72652E63000090310108E7 +:10E0900078EB000810B500244FF42051124800F02E +:10E0A0006DFC00211148C0F8B410FEF7A7FC002059 +:10E0B00000F0D0FC044634B90DA117A000F028F9F7 +:10E0C0004FF0FF3010BDFFF7D3FB48B116A112A0EF +:10E0D00000F01EF92046FFF781FE4FF0FF30F1E718 +:10E0E000FEF768FA0020EDE7102901204C280120F6 +:10E0F00073676C5F696E69743A20637265617465F9 +:10E100002073637265656E206F626A656374206652 +:10E1100061696C65640000001B5B33316D5B4552C7 +:10E12000524F525D0000000073676C5F696E697446 +:10E130003A206576656E7420717565756520696E27 +:10E140006974206661696C6564000000F0B585B093 +:10E1500007460D4616462C4600BF206B20B93022DC +:10E16000214922A0FEF7FEF900BFB0890F2839D15E +:10E1700094F83900C0F3801068B194F83800019029 +:10E18000E08EADF80000688D030905F1080229460C +:10E190003846FEF7BFFD94F8390000F03F000090CC +:10E1A000002305F10800D4E90B21FFF70BFF0490D1 +:10E1B00094F83810206BCDE90210A08EADF8040061 +:10E1C000E06A0090BDF8121094F93B00084403B2D5 +:10E1D000BDF8100094F93A10084402B229463846B6 +:10E1E000FFF725FA05B0F0BDC05D01082E2E5C5585 +:10E1F0007365725C73797374656D5C73676C5C775F +:10E200006964676574735C6C6162656C5C73676C90 +:10E210005F6C6162656C2E6300000000F8B5064615 +:10E220003C2000F0D1FA04462CB916A11DA000F044 +:10E230006FF80020F8BD3C212046F2F7ACF82546E7 +:10E240003146204600F0C0FD1A48A861FF202C345A +:10E250002073607B20F04000607300200090BDF8C8 +:10E260000000208112A020600020E081607B20F06F +:10E270008000607300BF1048D0F8C00060602C3C84 +:10E280002846D7E773676C5F6C6162656C5F637289 +:10E29000656174653A206D616C6C6F6320666169BD +:10E2A0006C6564001B5B33316D5B4552524F525DB0 +:10E2B000000000004DE100084C28012070B5044624 +:10E2C0000D4626463563204600F0ACFF70BD70B5A4 +:10E2D00004460D462646F562204600F0A3FF70BDB9 +:10E2E00070B504460E46254695F8390066F30500DC +:10E2F00085F83900204600F095FF70BD73B50446DF +:10E300002546BDF80400A886204600F08BFF7CBDA2 +:10E310000FB4F0B59FB0044600252046F2F746F84A +:10E320000746214601A8F2F756F826A8009001A951 +:10E33000C8197821009B259A01F09CFB00200090D1 +:10E3400001A8F2F733F8054601A828440AA10A6893 +:10E35000026089888180002101AAA81D115401AEA4 +:10E360000748006818B1064801683046884700BF72 +:10E370001FB0F0BC5DF814FB0D0A1B5B306D000094 +:10E380004C28012070B504460D462668E9B2304697 +:10E3900000F010FA70BD00002DE9F0472DED028B62 +:10E3A0008AB007460C4690462546A0882188401A28 +:10E3B000401C0FFA80F9E0886188401A401C0FFA6F +:10E3C00080FA1A2099FBF0F000EE100AB8EEC00AAD +:10E3D000B0EE408A0E209AFBF0F000EE100AB8EE84 +:10E3E000C00AF0EE408AB8F80C000F287DD106AEC6 +:10E3F000324621463846FDF71BFF20B90AB0BDEC76 +:10E40000028BBDE8F087002680E0B4F9000000EE42 +:10E41000100AB8EEC00AC54810F8260000EE900AAF +:10E42000F8EE600A00EE880ABDEEC00A10EE100A8F +:10E4300000B2ADF82000B4F9020000EE100AB8EE08 +:10E44000C00ABA4800EB8600407800EE900AF8EE69 +:10E45000600A00EEA80ABDEEC00A10EE100A00B273 +:10E46000ADF82200B4F9000000EE100AB8EEC00AC0 +:10E47000AE4800EB8600807800EE900AF8EE600A65 +:10E4800000EE880AF7EE000A30EE600ABDEEC00A20 +:10E4900010EE100A00B2ADF82400B4F9020000EE4C +:10E4A000100AB8EEC00AA14800EB8600C07800EE62 +:10E4B000900AF8EE600A00EEA80AF7EE000A30EEC5 +:10E4C000600ABDEEC00A10EE100A00B2ADF82600D8 +:10E4D0009748006805909648001D0068049095F8DC +:10E4E0002D000021CDE9021000E01DE1BDF8100073 +:10E4F000ADF80400BDF81400ADF80000608D03090C +:10E5000008AA06A93846FEF7BEFE761C052EFFF4C3 +:10E510007CAF00267FE0B4F9000000EE100AB8EEF0 +:10E52000C00A844810F8260000EE900AF8EE600A4F +:10E5300000EE880ABDEEC00A10EE100A00B2ADF877 +:10E540002000B4F9020000EE100AB8EEC00A7948C3 +:10E5500000EB8600407800EE900AF8EE600A00EECC +:10E56000A80ABDEEC00A10EE100A00B2ADF82200F3 +:10E57000B4F9000000EE100AB8EEC00A6D4800EBD6 +:10E580008600807800EE900AF8EE600A00EE880AB5 +:10E59000F7EE000A30EE600ABDEEC00A10EE100A77 +:10E5A00000B2ADF82400B4F9020000EE100AB8EE93 +:10E5B000C00A604800EB8600C07800EE900AF8EED2 +:10E5C000600A00EEA80AF7EE000A30EE600ABDEE1F +:10E5D000C00A10EE100A00B2ADF826005448083008 +:10E5E0000068059052480C300068049095F82D00A2 +:10E5F0000021CDE90210BDF81000ADF80400BDF80F +:10E600001400ADF80000608D030908AA06A9384679 +:10E61000FEF739FE761C052EFFF47DAF00267FE065 +:10E62000B4F9000000EE100AB8EEC00A424810F833 +:10E63000260000EE900AF8EE600A00EE880ABDEEB1 +:10E64000C00A10EE100A00B2ADF82000B4F90200C2 +:10E6500000EE100AB8EEC00A374800EB860040789A +:10E6600000EE900AF8EE600A00EEA80ABDEEC00ABD +:10E6700010EE100A00B2ADF82200B4F9000000EE6E +:10E68000100AB8EEC00A2C4800EB8600807800EE35 +:10E69000900AF8EE600A00EE880AF7EE000A30EE03 +:10E6A000600ABDEEC00A10EE100A00B2ADF82400F8 +:10E6B000B4F9020000EE100AB8EEC00A1E4800EBE2 +:10E6C0008600C07800EE900AF8EE600A00EEA80A14 +:10E6D000F7EE000A30EE600ABDEEC00A10EE100A36 +:10E6E00000B2ADF8260012481030006805901048BE +:10E6F00014300068049095F82D000021CDE9021037 +:10E70000BDF81000ADF80400BDF81400ADF800002D +:10E71000608D030908AA06A93846FEF7B4FD761CE9 +:10E72000022EFFF47DAF00BF00BF67E66C39010821 +:10E73000803A0108803901089439010870B506460D +:10E74000302000F041F804462CB90DA114A0FFF7C9 +:10E75000DFFD002070BD30212046F1F71CFE25466C +:10E760003146204600F030FB1148A861FF2084F8B4 +:10E770002D000021284600F0DFFC2846EAE70000D3 +:10E7800073676C5F6C6F676F5F6372656174653A26 +:10E79000206D616C6C6F63206661696C656400005C +:10E7A0001B5B33316D5B4552524F525D00000000E0 +:10E7B00099E3000870B504460D46264686F82D50AC +:10E7C000204600F083FD70BD70B505462846FCF775 +:10E7D000F9F904462CB908A10BA0FFF799FD002018 +:10E7E00070BD2046FCF7C4F90B49896808440A4902 +:10E7F00088602046F4E700006F7574206F66206D16 +:10E80000656D6F72790000001B5B33316D5B4552A3 +:10E81000524F525D000000001C520120F0B502462C +:10E82000B2F90000B1F90460B04205DDB2F90000B0 +:10E83000B1F90460801B0CE0B1F90000B2F904608A +:10E84000B04205DDB1F90000B2F90460801B00E0C0 +:10E85000002004B2B2F90200B1F90660B04205DD51 +:10E86000B2F90200B1F90660801B0CE0B1F90200B8 +:10E87000B2F90660B04205DDB1F90200B2F90660F6 +:10E88000801B00E0002005B2B2F90400B2F900607C +:10E89000801B401CB2F90660B2F90270F61B761CB0 +:10E8A000B04206DAB2F90400B2F90060801B401CE5 +:10E8B00005E0B2F90600B2F90260801B401CB1F914 +:10E8C0000460B1F90070F61B761CB1F90670B1F95D +:10E8D00002C0A7EB0C077F1CBE4206DAB1F9046048 +:10E8E000B1F90070F61B761C05E0B1F90660B1F9CC +:10E8F0000270F61B761CB0421BDAB2F90400B2F9C2 +:10E900000060801B401CB2F90660B2F90270F61B71 +:10E91000761CB04206DAB2F90400B2F90060801B3E +:10E92000401C21E0B2F90600B2F90260801B401CD5 +:10E930001AE0B1F90400B1F90060801B401CB1F984 +:10E940000660B1F90270F61B761CB04206DAB1F926 +:10E950000400B1F90060801B401C05E0B1F906001D +:10E96000B1F90260801B401C83109C4203DC9D4275 +:10E9700001DC0120F0BD0020FCE700007FB505466A +:10E980000C460020009001900290039000950194A5 +:10E990006846FCF78FF80348006820440149086086 +:10E9A0007FBD00001C52012070B504460D4600BF1B +:10E9B00004B125B98C22094909A0FDF7D3FD00BF98 +:10E9C000266A206A30B100E0766A706A0028FBD1BE +:10E9D000756200E02562EC6170BD0000E331010862 +:10E9E0002E2E5C557365725C73797374656D5C7300 +:10E9F000676C5C636F72655C73676C5F636F726595 +:10EA00002E63000010B5044600BF2CB940F2294225 +:10EA1000054906A0FDF7A6FD00BF94F8280020F0E8 +:10EA2000020084F8280010BDE33001082E2E5C554A +:10EA30007365725C73797374656D5C73676C5C6924 +:10EA40006E636C7564655C73676C5F636F72652E73 +:10EA50006800000070B5054665B900F063FD064624 +:10EA60002EB916A11EA0FFF753FC002070BD34463E +:10EA70002046FBE72C20FFF7A7FE04462CB91CA17B +:10EA800017A0FFF745FC0020F0E7A868A060E86841 +:10EA9000E060E561002020616061A06194F82800D9 +:10EAA00020F00200801C84F82800204600F0A6FA1E +:10EAB00021462846FFF778FF2046D7E773676C5F4B +:10EAC0006F626A5F6372656174653A206372656143 +:10EAD00074652070616765206661696C656400001B +:10EAE0001B5B33316D5B4552524F525D000000009D +:10EAF0006D616C6C6F63206661696C656400000019 +:10EB000070B504462CB100BF1948D0F8B400A0423B +:10EB100010D100BF1648D0F8B4000446206A10B1E6 +:10EB2000206A00F03DF8204600F068FA204600F028 +:10EB3000A3FB70BD94F82A00C0F3C00018B12046B2 +:10EB400000F02EF8F5E7254600BF00BF2DB940F2D2 +:10EB50000442084908A0FDF705FD00BF95F828000C +:10EB600020F00100401C85F8280000BF00BFE0E74E +:10EB70004C280120A63001082E2E5C557365725C6E +:10EB800073797374656D5C73676C5C696E636C75C7 +:10EB900064655C73676C5F636F72652E680000006C +:10EBA00030B591B0044600BF2CB94FF46B721849D0 +:10EBB00018A0FDF7D7FC00BF002528466D1C01A951 +:10EBC00041F8204020E000BF102D05DB40F2B232BA +:10EBD0000F4910A0FDF7C6FC00BF681E054601A93D +:10EBE00051F82040606A20B128466D1C626A41F8E5 +:10EBF0002020206A28B128466D1C01A9226A41F80C +:10EC000020202046FFF7EAF8002DDCDC11B030BDF3 +:10EC1000DB3201082E2E5C557365725C7379737458 +:10EC2000656D5C73676C5C636F72655C73676C5F6A +:10EC3000636F72652E6300007CB505460C4600BF0D +:10EC40002CB94FF4CB622D492DA0FDF78BFC00BFF2 +:10EC5000B4F9080094F829100844B4F90010884267 +:10EC600005DDB4F9080094F82910084401E0B4F96E +:10EC7000000000B2ADF80000B4F90A0094F82910C1 +:10EC80000844B4F90210884205DDB4F90A0094F88A +:10EC90002910084401E0B4F9020000B2ADF8020006 +:10ECA000B4F90C0094F82910401AB4F90410884201 +:10ECB00005DAB4F90C0094F82910401A01E0B4F90F +:10ECC000040000B2ADF80400B4F90E0094F8291065 +:10ECD000401AB4F90610884205DAB4F90E0094F827 +:10ECE0002910401A01E0B4F9060000B2ADF80600A0 +:10ECF00000982860019868607CBD000045310108DB +:10ED00002E2E5C557365725C73797374656D5C73DC +:10ED1000676C5C696E636C7564655C73676C5F637C +:10ED20006F72652E6800000010B5044600BF2CB954 +:10ED300040F23262054906A0FDF714FC00BFE189EC +:10ED40006089081A401C00B210BD0000D1390108CA +:10ED50002E2E5C557365725C73797374656D5C738C +:10ED6000676C5C696E636C7564655C73676C5F632C +:10ED70006F72652E6800000010B5044600BF2CB904 +:10ED800040F21962054906A0FDF7ECFB00BFA0891F +:10ED90002189401A401C00B210BD0000BF39010893 +:10EDA0002E2E5C557365725C73797374656D5C733C +:10EDB000676C5C696E636C7564655C73676C5F63DC +:10EDC0006F72652E6800000070B504460D4600BFE6 +:10EDD0002CB940F28732184918A0FDF7C3FB00BFD9 +:10EDE00065B900BF1E48D0F8B400054635B91DA16D +:10EDF00025A0FFF78DFA4FF0FF3070BDA8680C34E6 +:10EE000044F8040CE8682060256100206060A06080 +:10EE1000E060207F20F00200801C2077207F20F01F +:10EE2000400020770C3C2046FDF7B0FA21462846EA +:10EE3000FFF7BAFD0020E0E7CE3201082E2E5C5528 +:10EE40007365725C73797374656D5C73676C5C6316 +:10EE50006F72655C73676C5F636F72652E63000031 +:10EE60004C28012073676C5F6F626A5F696E69741A +:10EE70003A2068617665206E6F20616374697665FB +:10EE800020706167650000001B5B33316D5B45528C +:10EE9000524F525D0000000010B5044600BF2CB96F +:10EEA0004FF49662044905A0FDF75CFB00BF94F89F +:10EEB0002800C0F3801010BD593401082E2E5C5577 +:10EEC0007365725C73797374656D5C73676C5C6990 +:10EED0006E636C7564655C73676C5F636F72652EDF +:10EEE0006800000010B5044600BF2CB94FF49162D1 +:10EEF000044905A0FDF736FB00BF94F82800C0F3D5 +:10EF0000800010BD333101082E2E5C557365725C94 +:10EF100073797374656D5C73676C5C696E636C7533 +:10EF200064655C73676C5F636F72652E68000000D8 +:10EF3000F0B591B004460E46174600BF24B9C22270 +:10EF4000244925A0FDF70EFB00BF0025206A08B963 +:10EF500011B0F0BD28466D1C01A9226A41F820209D +:10EF600034E000BF102D04DBCC221A491AA0FDF7B3 +:10EF7000F9FA00BF681E054601A951F8204094F82F +:10EF8000280020F00200801C84F8280020893044EA +:10EF900000B22081A089304401B2A1816089384447 +:10EFA00001B26181E089384401B2E181606A28B12F +:10EFB00028466D1C01A9626A41F82020206A28B108 +:10EFC00028466D1C01A9226A41F82020002DC8DCCA +:10EFD00000BFBDE7043201082E2E5C557365725CDC +:10EFE00073797374656D5C73676C5C636F72655C79 +:10EFF00073676C5F636F72652E63000010B5044623 +:10F0000000BF2CB940F27E32044905A0FDF7AAFAF0 +:10F0100000BF00206062206210BD00009430010833 +:10F020002E2E5C557365725C73797374656D5C73B9 +:10F03000676C5C696E636C7564655C73676C5F6359 +:10F040006F72652E6800000070B5044600BF24B9D9 +:10F05000A5220C490CA0FDF785FA00BFE669002542 +:10F06000306AA04208D0356A00E06D6A686AA04242 +:10F07000FBD1606A686201E0606A30620020606211 +:10F0800070BD0000F53101082E2E5C557365725C71 +:10F0900073797374656D5C73676C5C636F72655CC8 +:10F0A00073676C5F636F72652E6300002DE9F0413A +:10F0B00004460F46904600BF24B9E922144915A022 +:10F0C000FDF750FA00BF2089381A05B26089A8EB15 +:10F0D000000006B294F8280020F00200801C84F89A +:10F0E00028002089284400B22081A089284401B248 +:10F0F000A1816089304401B26181E089304401B26C +:10F10000E181324629462046FFF712FFBDE8F08133 +:10F110001B3201082E2E5C557365725C7379737413 +:10F12000656D5C73676C5C636F72655C73676C5F65 +:10F13000636F72652E6300002DE9F84F04460D469B +:10F1400000BF2CB940F23F621F492048FDF70AFA80 +:10F1500000BF2046FFF710FE009000EBD07040107B +:10F16000A84201DDAB4607E02046FFF705FE8246D8 +:10F170000AEBDA704FEA600B2046FFF7D5FD8146B7 +:10F1800000EBD9704010834512DA2046FFF7F4FDFA +:10F19000804600EBD0704010A84201DD28460EE00A +:10F1A0002046FFF7E9FD074607EBD770401006E061 +:10F1B0002046FFF7B9FD064606EBD670401084F8EE +:10F1C0002900BDE8F88F0000E43901082CC70008C9 +:10F1D00010B5044600BF2CB940F21D42064907A0F5 +:10F1E000FDF7C0F900BF94F8280020F00200801C51 +:10F1F00084F8280010BD00007C2E01082E2E5C55DE +:10F200007365725C73797374656D5C73676C5C694C +:10F210006E636C7564655C73676C5F636F72652E9B +:10F220006800000010B5044600BF2CB940F21D4232 +:10F23000064907A0FDF796F900BF94F8280020F0D2 +:10F240000200801C84F8280010BD0000A42E0108D4 +:10F250002E2E5C557365725C73797374656D5C7387 +:10F26000676C5C696E636C7564655C73676C5F6327 +:10F270006F72652E6800000010B5044600BF2CB9FF +:10F2800040F21D42064907A0FDF76CF900BF94F853 +:10F29000280020F00200801C84F8280010BD000027 +:10F2A000D13001082E2E5C557365725C73797374CE +:10F2B000656D5C73676C5C696E636C7564655C73CB +:10F2C000676C5F636F72652E6800000010B50446BE +:10F2D00000BF2CB940F21D42064907A0FDF742F9D4 +:10F2E00000BF94F8280020F00200801C84F8280059 +:10F2F00010BD00009C3901082E2E5C557365725CB0 +:10F3000073797374656D5C73676C5C696E636C753F +:10F3100064655C73676C5F636F72652E68000000E4 +:10F3200070B504460D461646E0694089304402B285 +:10F33000E0690089284401B22046FFF7B7FE70BD9E +:10F3400030B587B004460D4600BF2CB940F21552C7 +:10F35000254926A0FDF706F900BF00200490039080 +:10F360000290A0892189401A401C00B2ADF8040027 +:10F37000E1896089081A401C00B2ADF80600E06916 +:10F380008089E1690989401A401C00B2ADF8180073 +:10F39000E069C1894089081A401C00B2ADF81A0022 +:10F3A00006980490E0690089ADF81400E06940898E +:10F3B000ADF81600059803902A4601A904A8FEF7A7 +:10F3C0001DFD0290BDF80E00BDF80A30184402B2CF +:10F3D000BDF80C00BDF80830184401B22046FFF714 +:10F3E00065FE07B030BD00004E3301082E2E5C557F +:10F3F0007365725C73797374656D5C73676C5C6361 +:10F400006F72655C73676C5F636F72652E6300007B +:10F41000F0B50A46838904891B1B5B1C1DB2C48995 +:10F420004389E31A5B1C1EB2B54201DD334600E09E +:10F430002B4619460B4601EBD37417B2B7EB640F9A +:10F440000CDB01F0010727B10C4604EBD4777F10E9 +:10F4500003E04B1E03EBD3777F103A46438D62F3F4 +:10F460000F134385F0BD000070B504460D461646E7 +:10F4700000BF2CB940F2EF5209490AA0FDF772F81B +:10F4800000BF20892844401E01B2A1816089304418 +:10F49000401E01B2E1812046FFF7C4FE70BD0000AE +:10F4A000B62E01082E2E5C557365725C73797374E9 +:10F4B000656D5C73676C5C696E636C7564655C73C9 +:10F4C000676C5F636F72652E680000002DE9FC4178 +:10F4D00080460C46164625462F6BB0890F281AD158 +:10F4E0006FB995F82E000190A88DADF800000023AB +:10F4F00004F1080221464046FDF70CFC10E095F8A7 +:10F500002E00002304F108022146CDE90070404698 +:10F51000FDF727FD04E0206910B1304621698847D6 +:10F52000BDE8FC813EB53420FFF74EF905462DB904 +:10F530002CA134A0FEF7ECFE00203EBD342128466D +:10F54000F0F729FF2C463348406840B932A12DA07E +:10F55000FEF7DEFE2846FEF741FC0020EDE73848C6 +:10F5600000680290BDF80800A885FF2085F82E00ED +:10F57000E46194F8280020F0400084F82800314825 +:10F58000A06194F8280020F00200801C84F8280074 +:10F59000608D20F0080008306085002084F8290084 +:10F5A000009001901B48008A401E00B2ADF8040094 +:10F5B0001848408A401E00B2ADF806000098A060CE +:10F5C0000198E060A0682060E06860602846FFF76E +:10F5D00015FD1048D0F8B40010B90E48C0F8B4506A +:10F5E0002846AAE773676C5F706167655F63726541 +:10F5F0006174653A206D616C6C6F63206661696C43 +:10F60000656400001B5B33316D5B4552524F525DA8 +:10F61000000000004C28012073676C5F7061676513 +:10F620005F6372656174653A206672616D656275CB +:10F6300066666572206973204E554C4C00000000D0 +:10F6400088320108CDF4000873B504462546BDF89C +:10F650000400A8852046FFF70FFE7CBD70B5044668 +:10F660000E46154600BF2CB940F24B72064907A062 +:10F67000FCF778FF00BF2188C1F30C0105FB016195 +:10F68000606800EB410070BD963A01082E2E5C5573 +:10F690007365725C73797374656D5C73676C5C69B8 +:10F6A0006E636C7564655C73676C5F636F72652E07 +:10F6B00068000000FEB50020029000BF2E48D0F880 +:10F6C000B40005460299FFF7BFFF0020FEF7A6FD34 +:10F6D0000446254600263746E8694089384402B288 +:10F6E000E8690089304401B22846FFF7DFFC00BF1B +:10F6F0002546F026374600BF00BF2DB940F2EF5235 +:10F700001E491FA0FCF72EFF00BF28893044401E71 +:10F7100001B2A98168893844401E01B2E9812846B6 +:10F72000FFF756FD00BF20A52646F5622046FFF7ED +:10F730004FFD00BF1F4D264635632046FFF748FDAD +:10F7400000BF1D4800680190019800902546BDF853 +:10F750000000A8862046FFF73BFD00BF0025264697 +:10F7600096F8390065F3050086F839002046FFF762 +:10F770002FFD00BFFEBD00004C2801208E2E010889 +:10F780002E2E5C557365725C73797374656D5C7352 +:10F79000676C5C696E636C7564655C73676C5F63F2 +:10F7A0006F72652E6800000048656C6C6F20576FA3 +:10F7B000726C6400A85D0108A02E01082DE9F047D5 +:10F7C000074688464FF00009CA4600264546FC68B1 +:10F7D000012007E0D4E900121144A94200D904E055 +:10F7E0001034401C39698142F4D800BF20682D1ABA +:10F7F000A06868B96068A84207D84246164917A0B1 +:10F80000FEF786FD0020BDE8F087E0682844FAE7AF +:10F810006068A0F1010A15E0AAEB090009EB5006A7 +:10F82000A06850F82600A84202D1E0683044EAE718 +:10F83000A06850F82600A84202D206F1010901E0B2 +:10F84000A6F1010AD145E7D94246034903A0FEF7D4 +:10F850005FFD0020D7E70000F86001081B5B333331 +:10F860006D5B5741524E5D00F0B502464FF4804546 +:10F8700000260027B2F5806F02D81E48805CF0BDDC +:10F88000B2F1804F01D90020F9E700231146080C9E +:10F89000000408B91033090401F07F4008B90833A7 +:10F8A000090201F0704008B91B1D090101F0404038 +:10F8B00008B99B1C890001F0004000B95B1CC3F132 +:10F8C0001F00DFF834C01CF8007078000E304FF0D5 +:10F8D000010C0CFA00F500BFAC19A24201D3121BB7 +:10F8E0002E1952006808051EF6D126FA07F0C0B29C +:10F8F000C5E7000048350108493901082DE9F04104 +:10F9000007460E463C46354600BF00BF04B12DB940 +:10F9100040F2597210491148FCF724FE00BFB5F9B6 +:10F920000200B4F90610884211DCB5F90600B4F9FA +:10F93000021088420BDBB5F90000B4F904108842CC +:10F9400005DCB5F90400B4F90010884202DA0020A1 +:10F95000BDE8F0810120FBE76931010878EB000880 +:10F9600070B504460D461646324629462046FCF739 +:10F970005FFC70BD10B503461C8A02FB0414986836 +:10F9800000EB440010BD000010B500BF0B48D0F8DC +:10F99000BC0000BF0949D1F8B810401A0A2800D2AB +:10F9A00010BD00BF0548D0F8BC000449C1F8B8003C +:10F9B00000BF00F005F800BFF2E700004C2801206E +:10F9C00010B5FDF7ABFFFCF7B3FB0549D1F8B40068 +:10F9D000FCF728FF0248001DFDF75CFE10BD00008B +:10F9E0004C28012010B503460A461946087880289D +:10F9F00003DA08781060012010BD087800F0E000FC +:10FA0000C02808D1087800F01F04487864F39F10DC +:10FA100010600220F0E7087800F0F000E0280ED136 +:10FA200008780007000C4C7804F03F0440EA84108A +:10FA30008C7804F03F04204310600320DCE7087852 +:10FA400000F0F800F02813D108784007C00A4C787D +:10FA500004F03F0440EA04308C7804F03F0440EAAC +:10FA60008410CC7804F03F04204310600420C3E7E6 +:10FA70000020C1E72DE9FF4F2DED028B87B007462F +:10FA80000D46144600200690CCE094F800B0BBF17F +:10FA9000250F07D05B4606AA29463846FAF76EFBC3 +:10FAA000641CBFE0641C0020059080464FF0FF39C5 +:10FAB00020782D2802D101200590641C06E02078D2 +:10FAC000303808EB880100EB4108641C20783028AE +:10FAD00002DB20783928F2DD20782E2810D1641C32 +:10FAE0004FF0000906E02078303809EB890100EB7F +:10FAF0004109641C2078302802DB20783928F2DDA7 +:10FB000094F800A0BAF1640F2BD009DCBAF1250FEC +:10FB100071D0BAF1580F3DD0BAF1630F72D15CE0E9 +:10FB2000BAF1660F42D0BAF1730F03D0BAF1780F71 +:10FB300068D123E00C98006804900C98001D0C908C +:10FB400006A8CDE901750390049E05E016F8013B77 +:10FB500001A807C8FAF712FB30780028F6D100BFD9 +:10FB60005DE00C9840C80C900598334606AA2946DB +:10FB7000CDE900803846FAF7C9FB50E00C9840C840 +:10FB80000C900020334606AA294600903846FAF722 +:10FB90007DFB44E00C9840C80C900120334606AA37 +:10FBA000294600903846FAF771FB38E00C98C01DE2 +:10FBB00020F007000C90B0EC020BB0EE408AF0EEA3 +:10FBC000608A0C904B46B0EE480AF0EE680A06AA2E +:10FBD00029463846FAF7DEFA21E00C9810F8041BA3 +:10FBE000CEB20C90334606AA29463846FAF7C6FA32 +:10FBF00015E000E006E0252306AA29463846FAF774 +:10FC0000BDFA0CE0252306AA29463846FAF7B6FACB +:10FC1000534606AA29463846FAF7B0FA00BF00BF95 +:10FC2000641C00BF207800287FF42FAF3DB1002175 +:10FC30000698A84201D2069800E0681E395406983A +:10FC400007B0BDEC028B04B0BDE8F08F0146002088 +:10FC500009E0074A52F820201AB9054A42F8201054 +:10FC60007047421C10B20528F3DB00BFF8E7000024 +:10FC70003824012010B504460121204600F075F813 +:10FC800010BD000010B50446226891682069F0F7A5 +:10FC900094FB60B994F8600020F00100401C84F8E7 +:10FCA000600008480168204601F066FB04E0054852 +:10FCB000416B204601F060FB0020A0810021E18122 +:10FCC00010BD0000D80100200246087858B14878DD +:10FCD00000F00F00082806D0106878B10878136883 +:10FCE0001B78184050B192F8600000F0010018B97C +:10FCF0004878C0F3001008B1002070474FF0FF3083 +:10FD0000FBE7000010B500F01BFB044624B10348DC +:10FD1000816B204601F030FB10BD0000D8010020AF +:10FD200070B50446A189E089081A05B205E02021D2 +:10FD3000204601F03BFA681E05B2002DF7DC217B5E +:10FD4000204600F07FF870BD10B500F0F9FA0446C7 +:10FD500014B1204600F054FD10BD10B504464FF01C +:10FD6000FF31204600F001F810BD2DE9F0410446B6 +:10FD70000D46681C08B9012000E000200746E08914 +:10FD800008B9012D05D0E089A189884203D1681CFA +:10FD900008B9BDE8F081E089A189884210D1012D20 +:10FDA0000ED1E089401EE081A089401EA081002183 +:10FDB000A289206981540121204600F043F83FE0E8 +:10FDC00038460AE0E18901442269525CE189014434 +:10FDD000491E23695A54411C08B2A289E189511A6B +:10FDE0008142EFDCA089401EA08137B9E089401E26 +:10FDF000E0810821204601F0D9F90021A28920697B +:10FE00008154E08906B206E02069815D204601F058 +:10FE1000CDF9701C06B2A089B042F5DC2021204645 +:10FE200001F0C4F9A189E089081A401C06B205E076 +:10FE30000821204601F0BAF9701E06B2002EF7DC48 +:10FE400000BFA6E770B505460C4603E004A12846AE +:10FE500001F092FA201EA4F10101CCB2F6D170BDDE +:10FE60000820080010B504464FF0FF31204600F08E +:10FE700041FB10BD10B50446204600F005F80121F5 +:10FE8000204601F0FFF910BD70B50446A08900B905 +:10FE900070BD0021A2892069815494F8600000F0AF +:10FEA000010010B3204600F086FB204600F0DEFD86 +:10FEB0000021E181A181E08E00B9E9E70DA1204692 +:10FEC00001F05AFA00232046A26D616900F077FE26 +:10FED000054625B12946204600F018FE04E00648F4 +:10FEE0008169204601F048FA02E02046FFF7CAFE89 +:10FEF00000BFCDE70D0A0000D801002010B5024672 +:10FF0000114600200B78302B07D14B78782B02D08C +:10FF10004B78582B01D103200EE00B78302B07D102 +:10FF20004B78622B02D04B78422B01D1012003E0A9 +:10FF30000B78302B00D1022006E00B782E2B03D15A +:10FF40004B780BB1042003E011F8014B002CF4D1E5 +:10FF500000BF10BD02461378272B01D1531C00E0CF +:10FF60001346194600200B785C2B1AD14B786E2B68 +:10FF70000ED004DC302B0FD0622B0FD104E0722B9B +:10FF800004D0742B0AD105E0082009E00D2007E019 +:10FF90000A2005E0092003E0002001E0487800BFC6 +:10FFA00000E00878704700002DE9F84F05464FF053 +:10FFB000000A4FF00A0B2C46002000900126002773 +:10FFC0009FED330A10EE109A804628782D2800D134 +:10FFD000B61E711C09B9012100E000214819FFF784 +:10FFE0008DFF8246BAF1010F0FD0BAF1020F07D090 +:10FFF000BAF1030F0ED14FF0100B022000900AE06F :020000040801F1 -:10000000C060F8E360CCFE31C39831308031FF0F1F -:100010001B0C0C1B06060E3C070EE0031BE0C33155 -:100020003C76E0071880000000000000CAFD2000B8 -:1000300000000000000000000000000000000000C0 -:1000400000000000000000000000000000000000B0 -:1000500000000000000000000000000000000000A0 -:100060000000000000000000000000000000000090 -:100070000000000000000000000000000000000080 -:1000800030000330000330FEFF300003300003FF78 -:10009000FD7F300C6030FC7F300C6030FC7F300C1A -:1000A00060B0FD7F780C6007FFFF00601C001CF053 -:1000B000800300000000000000000000CCEE2000E3 -:1000C0000000000000000000000000000000000030 -:1000D0000000000000000000000000000000000020 -:1000E0000000000000000000000000000000000010 -:1000F0000000000000000000000000000000000000 -:1001000000000000000000000000000000000000EF -:10011000000800001800003800FFFFFF000E0080FC -:100120008301C0000770000CFCFF3F00C32000C328 -:100130000080C10080C1C0E0C0C038C0C007807F5F -:10014000000000000000000000000000B3E42000F8 -:10015000000000000000000000000000000000009F -:10016000000000000000000000000000000000008F -:10017000000000000000000000000000000000007F -:10018000000000000000000000000000000000006F -:10019000000000000000000000000000000000005F -:1001A000003800007000FEFFFF0600C00686C3C0D6 -:1001B000011E3800700600C0000000F8FF3F001864 -:1001C00000001800001800001800001800FEFFFFD3 -:1001D000000000000000000000000000BFD520006B -:1001E000000000000000000000000000000000000F -:1001F00000000000000000000000000000000000FF -:1002000000000000000000000000000000000000EE -:1002100000000000000000000000000000000000DE -:1002200000000000000000000000000000000000CE -:1002300030600030300030F07F307870FF5B383055 -:10024000CC0CF88007B8C10F3C7A78360EC033F872 -:100250007F31186030186030186030186030F87FD7 -:10026000301860000000000000000000B8F120001D -:10027000000000000000000000000000000000007E -:10028000000000000000000000000000000000006E -:10029000000000000000000000000000000000005E -:1002A000000000000000000000000000000000004E -:1002B000000000000000000000000000000000003E -:1002C000000000000000000000000000000000002E -:1002D000000000000000000000000000000000001E -:1002E000000000000000000000000000000000000E -:1002F00000000000000000000000000000000000FE -:1003000000000000000000000000000000000000ED -:1003100000000000000000000000000000000000DD -:1003200000000000000000000000000000000000CD -:1003300000000000000000000000000000000000BD -:1003400000000000000000000000000000000000AD -:10035000000000000000000000000000000000009D -:10036000000000000000000000000000000000008D -:10037000000000000000000000000000000000007D -:10038000000000000000000000000000000000006D -:1003900000000000008000000000030000000300D7 -:1003A0002000020CE0FFFF1F60300C0060300C00EA -:1003B00060300C04E0FFFF0F60300C0460300C0470 -:1003C00060300C0460300C04E0FFFF0760000004A4 -:1003D0006000040060041C00600C0C0460040C0F3E -:1003E00060C48C0320FCED0020041C0030040C00D1 -:1003F00010040D0810C40C0808340C18081E183816 -:10040000040CF81F0200000000000000C2B9200028 -:1004100000000000000000000000000000000000DC -:1004200000000000000000000000000000000000CC -:1004300000000000000000000000000000000000BC -:1004400000000000000000000000000000000000AC -:10045000000000000000000000000000000000009C -:10046000000000000000000000000000000000008C -:10047000000000000000000000000000000000007C -:10048000000000000000000000000000000000006C -:1004900000000000008000000080070000800100D4 -:1004A0000080010000800100008001000080010048 -:1004B0000080010000820100008E210000864100C2 -:1004C0000087810000838101808101038081010612 -:1004D000C080010E4080011C6080011C308001182A -:1004E00010800118088001100480010000800100C4 -:1004F0000080010000800100008C010000F001007C -:1005000000E000000040000000000000D0A120003A -:1005100000000000000000000000000000000000DB -:1005200000000000000000000000000000000000CB -:1005300000000000000000000000000000000000BB -:1005400000000000000000000000000000000000AB -:10055000000000000000000000000000000000009B -:10056000000000000000000000000000000000008B -:10057000000000000000000000000000000000007B -:10058000000000000000000000000000000000006B -:10059000000000000000010000000700000C03182C -:1005A000FC1FFF3FC0008301C0008301C000830126 -:1005B000C0008301C0008301C0008301C024830107 -:1005C000FC2F8301C0208309C020FF1FC03083019E -:1005D000C0188101C0008101C0008101C09081016B -:1005E000C08C8101C0838001F0C080013E40800149 -:1005F0000C208001003080110008FE3F0006000042 -:1006000000010000C000000000000000B0E0200079 -:1006100000000000000000000000000000000000DA -:1006200000000000000000000000000000000000CA -:1006300000000000000000000000000000000000BA -:1006400000000000000000000000000000000000AA -:10065000000000000000000000000000000000009A -:10066000000000000000000000000000000000008A -:10067000000000000000000000000000000000007A -:10068000000000000000000000000000000000006A -:10069000000000000000000100300007003C0003E3 -:1006A000E00700031C0300030003060300030C0320 -:1006B000000318030003180300230003FC7F00035A -:1006C000000300030003020380030603800F0C03F2 -:1006D000C03B0803403300336023003F2023F00376 -:1006E00010830F03086300030403000302030003E5 -:1006F00000030003000300030003000300030003E2 -:10070000000300030001000100000000BFC620003C -:1007100000000000000000000000000000000000D9 -:1007200000000000000000000000000000000000C9 -:1007300000000000000000000000000000000000B9 -:1007400000000000000000000000000000000000A9 -:100750000000000000000000000000000000000099 -:100760000000000000000000000000000000000089 -:100770000000000000000000000000000000000079 -:100780000000000000000000000000000000000069 -:100790000000000080001000800370008001300025 -:1007A0008001300080013000800130008019301855 -:1007B000FCFFFF3F800130008001300080013000ED -:1007C000800130008031300480CDFF0F80030106AE -:1007D000F0010106BC0102038C01020380018601C5 -:1007E000800184018001CC008001680080017000DC -:1007F000800178008001EC008001C703F881011FAF -:10080000E071003E400C000000000000BCBC200075 -:1008100000000000000000000000000000000000D8 -:1008200000000000000000000000000000000000C8 -:1008300000000000000000000000000000000000B8 -:1008400000000000000000000000000000000000A8 -:100850000000000000000000000000000000000098 -:100860000000000000000000000000000000000088 -:100870000000000000000000000000000000000078 -:100880000000000000000000000000000000000068 -:100890000000000000000000000000000000000058 -:1008A0000000000000000000000000000000000048 -:1008B0000000000000000000000000000000000038 -:1008C0000000000000000000000000000000000028 -:1008D0000000000000000000000000000000000018 -:1008E0000000000000000000000000000000000008 -:1008F00000000000000000000000000000000000F8 -:1009000000000000000000000000000000000000E7 -:1009100000000000000000000000000000000000D7 -:1009200000000000000000000000000000000000C7 -:1009300000000000000000000000000000000000B7 -:1009400000000000000000000000000000000000A7 -:100950000000000000000000000000000000000097 -:100960000000000000000000000000000000000087 -:100970000000000000000000000000000000000077 -:100980000000000000000000000000000000000067 -:100990000000000000000000000000000000000057 -:1009A0000000000000000000000000000000000047 -:1009B0000000000000000000000000000000000037 -:1009C0000000000000000000000000000000000027 -:1009D0000000000000000000000000000000000017 -:1009E0000000000000000000000000000000000007 -:1009F00000000000000000000000000000000000F7 -:100A000000000000000000000000000000000000E6 -:100A100000000000000000000000000000000000D6 -:100A200000000000000000000000000000000000C6 -:100A300000000000000000000000000000000000B6 -:100A400000000000000000000000000000000000A6 -:100A50000000000000000000000000000000000096 -:100A60000000000000000000000000000000000086 -:100A70000000000000000000000000000000000076 -:100A80000000000000000000000000000000000066 -:100A90000000000000000000000000000000000056 -:100AA0000000000000000000000000000000000046 -:100AB0000000000000000000000000000000000036 -:100AC0000000000000000000000000000000000026 -:100AD0000000000000000000000000000000000016 -:100AE0000000000000000000000000000000000006 -:100AF00000000000000000000000000000000000F6 -:100B000000000000000000000000000000000000E5 -:100B100000000000000000000000000000000000D5 -:100B200000000000000000000000000000000000C5 -:100B300000000000000000000000000000000000B5 -:100B400000000000000000000000000000000000A5 -:100B50000000000000000000000000000000000095 -:100B60000000000000000000000000000000000085 -:100B70000000000000000000000000000000000075 -:100B80000000000000000000000000000000000065 -:100B90000000000000000000000000000000000055 -:100BA0000000000000000000000000000000000045 -:100BB0000000000000000000000000000000000035 -:100BC0000000000000000000000000000000000025 -:100BD0000000000000000000000000000000000015 -:100BE0000000000000000000000000000000000005 -:100BF00000000000000000000000000000000000F5 -:100C000000000000000000000000000000000000E4 -:100C100000000000000000000000000000000000D4 -:100C200000000000000000000000000000000000C4 -:100C300000000000000000000000000000000000B4 -:100C400000000000000000000000000000000000A4 -:100C50000000000000000000000000000000000094 -:100C60000000000000000000000000000000000084 -:100C70000000000000000000000000000000000074 -:100C80000000000000000000000000000000000064 -:100C90000000000000000000000000000000000054 -:100CA0000000000000000000000000000000000044 -:100CB0000000000000000000000000000000000034 -:100CC0000000000000000000000000000000000024 -:100CD0000000000000000000000000000000000014 -:100CE0000000000000000000000000000000000004 -:100CF00000000000000000000000000000000000F4 -:100D000000000000000000000000000000000000E3 -:100D100000000000000000000000000000000000D3 -:100D200000000000000000000000000000000000C3 -:100D300000000000000000000000000000000000B3 -:100D400000000000000000000000000000000000A3 -:100D50000000000000000000000000000000000093 -:100D60000000000000000000000000000000000083 -:100D70000000000000000000000000000000000073 -:100D80000000000000000000000000000000000063 -:100D90000000000000000000000000000000000053 -:100DA0000000000000000000000000000000000043 -:100DB0000000000000000000000000000000000033 -:100DC0000000000000000000000000000000000023 -:100DD0000000000000000000C003C003C003C00307 -:100DE000C003C00380038001800180018001800175 -:100DF0008001800180010000000000008001C0032C -:100E0000C00380010000000000000000000000009E -:100E1000C018E01CE01C700E300618038C01840022 -:100E200000000000000000000000000000000000C2 -:100E300000000000000000000000000000000000B2 -:100E400000000000000000000000000000000000A2 -:100E500000000000000000002010201020102010D2 -:100E60002010FE7FFE7FFE7F10081008100810087B -:100E700010081008FE7FFE7FFE7F180C080408048F -:100E8000080408040000000000000000000000004A -:100E90000000000080008000C003B00C901898187B -:100EA000981C981CB800B000F000E000C003800758 -:100EB000800F800C801C80189C189C188C188C0C3F -:100EC0009806E00380008000800000000000000021 -:100ED00000000000000000001C0836082204630423 -:100EE000630263026302630163012201B61C9C3644 -:100EF000402240634063206320631063106310222C -:100F00000836081C0000000000000000000000007F -:100F10000000000000000000F00098008C018C012F -:100F20008C018C018C00CC005C0038001C3E3C081D -:100F3000320873086304E304C3048303834306672E -:100F40008C3E781C00000000000000000000000043 -:100F50001C003C003C003000300010000C0006007B -:100F60000000000000000000000000000000000081 -:100F70000000000000000000000000000000000071 -:100F80000000000000000000000000000000000061 -:100F90000040002000100018000C000400060002B1 -:100FA0000003000380018001800180018001800135 -:100FB000800180018001000300030002000600049C -:100FC000000C00180010002000400000000000008D -:100FD00002000400080018003000200060004000FB -:100FE000C000C0008001800180018001800180017B -:100FF000800180018001C000C000C00060002000AE -:10100000300018000800040002000000000000008A -:10101000000000000000000000000000000380034A -:1010200080030C631C713839600D80038003600DF0 -:1010300038391C718C61800380038003000000003C -:1010400000000000000000000000000000000000A0 -:10105000000000000000000000000000000000018F -:10106000000100010001000100010001FC7F0001FE -:10107000000100010001000100010001000000006A -:101080000000000000000000000000000000000060 -:101090000000000000000000000000000000000050 -:1010A0000000000000000000000000000000000040 -:1010B0000000000000000000000000001C003C00D8 -:1010C0003C003000300010000C0006000000000062 -:1010D0000000000000000000000000000000000010 -:1010E000000000000000000000000000FE7F000083 -:1010F00000000000000000000000000000000000F0 -:1011000000000000000000000000000000000000DF -:1011100000000000000000000000000000000000CF -:1011200000000000000000000000000000000000BF -:1011300000000000000000000000000018003C005B -:101140003C0018000000000000000000000000004B -:10115000000000400060002000300010001800086F -:10116000000C000400060002000300018001800062 -:10117000C00040006000200030001000180008008F -:101180000C00040006000200000000000000000047 -:101190000000000000000000C0036004300C1818BC -:1011A000181818100C300C300C300C300C300C307F -:1011B0000C300C300C300C30181018181818300C7B -:1011C0006004C003000000000000000000000000F8 -:1011D000000000000000000000018001F801800113 -:1011E00080018001800180018001800180018001F7 -:1011F00080018001800180018001800180018001E7 -:10120000C003F81F00000000000000000000000004 -:101210000000000000000000E007101C0818043067 -:1012200004300C300C30003000180018000C0006A0 -:1012300000038001C000400020201020082004305E -:10124000FC1FFC1F00000000000000000000000068 -:101250000000000000000000E00318060C0C0C1851 -:101260000C180C1800180018000C0006C003000E23 -:1012700000180010003000300C300C300C100C182E -:10128000180CE00300000000000000000000000057 -:101290000000000000000000000600060007000734 -:1012A0008006800640062006200610061006080666 -:1012B0000C0604060206FE3F0006000600060006B5 -:1012C0000006C03F00000000000000000000000019 -:1012D0000000000000000000F03FF03F08000800A0 -:1012E0000800080008000800C807280C1818081093 -:1012F00000300030003000300C300C30041804187E -:10130000180CE003000000000000000000000000D6 -:10131000000000000000000080076018301810185E -:101320001800080008000C00CC076C0C1C181C10DE -:101330000C300C300C300C300C30183018103018C9 -:10134000700CC0070000000000000000000000005A -:101350000000000000000000F83FF83F08100C08F3 -:10136000040804040004000200020002000100015D -:101370008000800080008000C000C000C000C0006D -:10138000C000C000000000000000000000000000DD -:101390000000000000000000E007300C18180C30BE -:1013A0000C300C301C301C107818F004E003180FBF -:1013B0000C1E0C1C063806300630063006300C18A1 -:1013C000180CE00300000000000000000000000016 -:1013D0000000000000000000E00318040C080C18D6 -:1013E0000610063006300630063006300E380C3453 -:1013F0001836F03100300018001800080C0C0C06EC -:101400000C03F001000000000000000000000000DC -:1014100000000000000000000000000000000000CC -:101420000000000000008001C003C0038001000034 -:101430000000000000000000000000008001C00368 -:10144000C003800100000000000000000000000058 -:10145000000000000000000000000000000000008C -:101460000000000000000000C001C001C001000039 -:101470000000000000000000000000000000C001AB -:10148000C001C0018001C000C000000000000000D9 -:101490000000000000000000002000100008000410 -:1014A0000002000180004000200010000800080039 -:1014B000100020004000800000010002000400082D -:1014C00000100020000000000000000000000000EC -:1014D000000000000000000000000000000000000C -:1014E000000000000000FE7F00000000000000007F -:1014F0000000FE7F0000000000000000000000006F -:1015000000000000000000000000000000000000DB -:10151000000000000000000004000800100020008F -:1015200040008000000100020004000800100010CC -:1015300000080004000200018000400020001000AC -:10154000080004000000000000000000000000008F -:101550000000000000000000C007301818300860CC -:101560000C601C601C601C6000300018000E000342 -:101570000001000100010001000000008001C00323 -:10158000C003800100000000000000000000000017 -:101590000000000000000000C007600830101820A4 -:1015A0000C2B8C4D844CC64CC64466446644664441 -:1015B0006646662666266417CC0C0C400820183058 -:1015C0003018C0070000000000000000000000000C -:1015D0000000000000000000C001C001C001C00107 -:1015E00020032003200320033002100610061006FB -:1015F0001004F80F080C080C080C04180418041840 -:1016000006381F7C00000000000000000000000001 -:101610000000000000000000FE07181C1818183019 -:1016200018301830183018301818180CF807181817 -:10163000183018201860186018601860186018308A -:101640001818FE0F0000000000000000000000005D -:101650000000000000000000C00760381030186073 -:101660000C400C400C0006000600060006000600B8 -:1016700006000600060006000C400C40082018106A -:101680003008C0070000000000000000000000005B -:101690000000000000000000FE03180E18181810CB -:1016A00018301830186018601860186018601860DA -:1016B000186018601860182018301830181818189A -:1016C0001806FE03000000000000000000000000FB -:1016D0000000000000000000FE3F183018201840F5 -:1016E00018401800180018081808180CF80F180CE3 -:1016F000180818081800180018001840184018207A -:101700001830FE3F00000000000000000000000054 -:101710000000000000000000FE3F183818201840AC -:1017200018401800180018081808180CF80F180CA2 -:1017300018081808180818001800180018001800D1 -:1017400018007E0000000000000000000000000003 -:101750000000000000000000C003300C1008181842 -:101760000C100C100400060006000600060006001F -:10177000067E0618061804180C180C1808181818F5 -:101780003004E00300000000000000000000000042 -:1017900000000000000000003FFC0C300C300C305A -:1017A0000C300C300C300C300C300C30FC3F0C305A -:1017B0000C300C300C300C300C300C300C300C3049 -:1017C0000C303FFC000000000000000000000000A2 -:1017D0000000000000000000F81F8001800180016F -:1017E00080018001800180018001800180018001F1 -:1017F00080018001800180018001800180018001E1 -:101800008001F81F00000000000000000000000040 -:101810000000000000000000E07F00060006000657 -:101820000006000600060006000600060006000688 -:101830000006000600060006000600060006000678 -:10184000000600060E060E038E01FC0000000000DC -:1018500000000000000000007E3E180C180418066E -:1018600018021801180198009800D800B801B801B2 -:101870001803180318061806180C180C180C18185A -:1018800018187E7C0000000000000000000000002E -:1018900000000000000000007E0018001800180082 -:1018A0001800180018001800180018001800180078 -:1018B00018001800180018001800184018401820C8 -:1018C0001830FE3F00000000000000000000000093 -:1018D00000000000000000000FF01C381C381C380D -:1018E0001C381C34343434343434343234326432BA -:1018F0006432643264314431C431C431C430C430E0 -:1019000084308FFC00000000000000000000000098 -:1019100000000000000000000FF81C201C203420F4 -:10192000342064206420C420C42084218421042322 -:10193000042304260426042C042C04380438043020 -:1019400004301F2000000000000000000000000024 -:101950000000000000000000C003300C1818081040 -:101960000C300C30062006600660066006600660DB -:1019700006600660066004600C300C300810181811 -:10198000300CC00300000000000000000000000058 -:101990000000000000000000FE0F1818183018604A -:1019A0001860186018601860186018301818F80768 -:1019B0001800180018001800180018001800180067 -:1019C00018007E0000000000000000000000000081 -:1019D0000000000000000000C003300C18180810C0 -:1019E0000C300C300660066006600660066006601B -:1019F0000660066006600660E4211C331C36181E73 -:101A0000300EC007004C003C003800000000000011 -:101A10000000000000000000FE07181C1818183015 -:101A200018301830183018301818180CF807180328 -:101A30001803180618061806180C180C180C181895 -:101A400018187E7800000000000000000000000070 -:101A50000000000000000000F013181E0C1806180B -:101A60000610061006000E003C00F800E003800F90 -:101A7000001E0018003802300230063004300C1806 -:101A80001C0CE40700000000000000000000000043 -:101A90000000000000000000FC3F8C2184618241B6 -:101AA00082418001800180018001800180018001EC -:101AB000800180018001800180018001800180011E -:101AC0008001E007000000000000000000000000AE -:101AD00000000000000000003F7C0C100C100C10F7 -:101AE0000C100C100C100C100C100C100C100C1016 -:101AF0000C100C100C100C100C100C100C10180802 -:101B00003804E003000000000000000000000000B6 -:101B100000000000000000003E7818301810181077 -:101B200018103008300830083008300460046004B1 -:101B300060046002C002C002C002C00180018001D6 -:101B40008000800000000000000000000000000095 -:101B50000000000000000000CFF386618621842190 -:101B600004210C238C238C238C138C138813481290 -:101B700058165816580E380E300E300E300C3004F1 -:101B8000100410040000000000000000000000002D -:101B900000000000000000003E7C1810180830080B -:101BA000300460046002C002C00180018001800135 -:101BB0008003400340062006200E100C100C18185D -:101BC00008383E7C0000000000000000000000001B -:101BD00000000000000000007E7C1C101810180897 -:101BE00030083008300460046004C002C002C00144 -:101BF00080018001800180018001800180018001DD -:101C00008001E0070000000000000000000000006C -:101C10000000000000000000F87F383018300C1879 -:101C20000418000C00060006000300038001800178 -:101C3000C000C000600060003000184018600C2038 -:101C40000C38FE3F00000000000000000000000013 -:101C50000000C03FC000C000C000C000C000C00005 -:101C6000C000C000C000C000C000C000C000C00074 -:101C7000C000C000C000C000C000C000C000C00064 -:101C8000C000C000C000C03F000000000000000015 -:101C900000000000000018001800100030002000B4 -:101CA000600060004000C0008000800180010001F1 -:101CB0000003000200060006000C000C000C0018D7 -:101CC000001800300030003000600000000000000C -:101CD0000000FC03000300030003000300030003F3 -:101CE00000030003000300030003000300030003DC -:101CF00000030003000300030003000300030003CC -:101D0000000300030003FC030000000000000000CB -:101D1000C003C007600410080000000000000000BD -:101D200000000000000000000000000000000000B3 -:101D300000000000000000000000000000000000A3 -:101D40000000000000000000000000000000000093 -:101D50000000000000000000000000000000000083 -:101D60000000000000000000000000000000000073 -:101D70000000000000000000000000000000000063 -:101D800000000000000000000000FFFF0000000055 -:101D90007800C0000001000000000000000000000A -:101DA0000000000000000000000000000000000033 -:101DB0000000000000000000000000000000000023 -:101DC0000000000000000000000000000000000013 -:101DD0000000000000000000000000000000000003 -:101DE000000000000000E007180C0C180C180C187C -:101DF000001CE01B38180C18061806180618069860 -:101E00000C9EF871000000000000000000000000BF -:101E100000000000000010001E001800180018004C -:101E20001800180018009807581C38183830183057 -:101E3000183018301830183018301830181038187A -:101E4000380CC8070000000000000000000000007F -:101E50000000000000000000000000000000000082 -:101E6000000000000000C0077008301818180C1897 -:101E70000C000C000C000C000C000C20182018109A -:101E80003008C00700000000000000000000000053 -:101E90000000000000000010001E001800180018CC -:101EA000001800180018E01B301C181818180C181F -:101EB0000C180C180C180C180C180C180818181CF6 -:101EC000307AE0090000000000000000000000007F -:101ED0000000000000000000000000000000000002 -:101EE000000000000000C003300C101818100C3067 -:101EF0000C300C30FC3F0C000C000C0018201810AB -:101F00007018C00700000000000000000000000082 -:101F10000000000000000000003E80618060C060A2 -:101F2000C000C000C000FC1FC000C000C000C00056 -:101F3000C000C000C000C000C000C000C000C000A1 -:101F4000C000F80F000000000000000000000000CA -:101F50000000000000000000000000000000000081 -:101F6000000000000000C077306C10181818181816 -:101F700018181018300CF00718001800F803F01F9C -:101F800018380C300C300C301818E0070000000036 -:101F900000000000000010001E00180018001800CB -:101FA0001800180018009807580C38181818181836 -:101FB00018181818181818181818181818181818A1 -:101FC00018187E7E000000000000000000000000E5 -:101FD00000000000000000008001C003800100003C -:101FE000000000000001F8018001800180018001F3 -:101FF00080018001800180018001800180018001D9 -:102000008001F81F00000000000000000000000038 -:102010000000000000000000001C001E000C00007A -:10202000000000000008C00F000C000C000C000CA9 -:10203000000C000C000C000C000C000C000C000C40 -:10204000000C000C000C18061802F0010000000043 -:1020500000000000000010001E001800180018000A -:10206000180018001800183E180C1804180218015F -:102070009801D801780338031806180C180C1818A2 -:1020800018387E7C00000000000000000000000006 -:102090000000000000000001F801800180018001C3 -:1020A0008001800180018001800180018001800128 -:1020B0008001800180018001800180018001800118 -:1020C0008001F81F00000000000000000000000078 -:1020D0000000000000000000000000000000000000 -:1020E000000000000400F73C8E6386618661866113 -:1020F00086618661866186618661866186618661A8 -:102100008661CFF300000000000000000000000026 -:1021100000000000000000000000000000000000BF -:1021200000000000000090075E0C381818181818FE -:10213000181818181818181818181818181818181F -:1021400018187E7E00000000000000000000000063 -:10215000000000000000000000000000000000007F -:10216000000000000000C003300C101818180830E0 -:102170000C300C300C300C300C300C301818181897 -:10218000300CC00300000000000000000000000050 -:10219000000000000000000000000000000000003F -:1021A00000000000000090075E0C3818181018306E -:1021B00018301830183018301830183018183818EF -:1021C000780C98071800180018007E000000000026 -:1021D00000000000000000000000000000000000FF -:1021E000000000000000C013301E181C18180C1846 -:1021F0000C180C180C180C180C180C180818181CB3 -:10220000301EE019001800180018007E00000000C1 -:1022100000000000000000000000000000000000BE -:1022200000000000000060387E666061E001E000B0 -:10223000600060006000600060006000600060009E -:102240006000FE0700000000000000000000000029 -:10225000000000000000000000000000000000007E -:10226000000000000000C0276038303030203020EF -:102270007000E003800F001E00380830083018306E -:102280003818C80F00000000000000000000000027 -:10229000000000000000000000000000800080003E -:1022A0008000C000E000FC1FC000C000C000C000F3 -:1022B000C000C000C000C000C000C000C020C020DE -:1022C0008011000F0000000000000000000000006E -:1022D00000000000000000000000000000000000FE -:1022E0000000000010101E1E1818181818181818D2 -:1022F0001818181818181818181818181818181C5A -:10230000307AE0090000000000000000000000003A -:1023100000000000000000000000000000000000BD -:102320000000000000003E7C18301810181830081B -:102330003008200460046004C002C002C0038001B1 -:10234000800180000000000000000000000000008C -:10235000000000000000000000000000000000007D -:10236000000000000000DFF3866184218C218C21B5 -:102370008C13881358135812580E700E300E300CF0 -:1023800030042004000000000000000000000000F5 -:10239000000000000000000000000000000000003D -:1023A0000000000000007C3E300870086004C0029D -:1023B000C00280018001800340062006200C101816 -:1023C00018183E7E00000000000000000000000021 -:1023D00000000000000000000000000000000000FD -:1023E0000000000000003E7C181818081008300893 -:1023F0002004600460044002C00280028001800169 -:1024000080008000800040007C003C000000000054 -:1024100000000000000000000000000000000000BC -:10242000000000000000FC1F0C1C0C0C040604073C -:1024300000038001C001C00060007020302018300F -:102440000C18FC1F0000000000000000000000004D -:10245000003000080004000400040004000400042C -:1024600000040004000400040004000380010002D2 -:10247000000400040004000400040004000400043C -:102480000004000400040008003000000001000106 -:102490000001000100010001000100010001000134 -:1024A0000001000100010001000100010001000124 -:1024B0000001000100010001000100010001000114 -:1024C0000001000100010001000100010000000006 -:1024D0001800200040004000400040004000400044 -:1024E00040004000400040004000800100038000A8 -:1024F00040004000400040004000400040004000DC -:10250000400040004000200018000000000078005B -:10251000C400824102410027001C000000000000AE -:1025200000000000000000000000000000000000AB -:10253000000000000000000000000000000000009B -:10254000000000000000000000000000000000008B -:10255000000000000000000000000000000000007B -:10256000000000000000000000000000000000006B -:10257000000000000000000000000000000000005B -:10258000000000006000600060006000600060000B -:10259000600040002000200020000000000000003B -:1025A000600060006000000000000000000000000B -:1025B00060066006300398018800440000000000B7 -:1025C000000000000000000000000000000000000B -:1025D00000000000000000000000000000000000FB -:1025E000000000001002100210021002FE07FE0799 -:1025F00008020801080108010801FE07FE0704019E -:1026000004010401040100000000000000000000BB -:10261000000040004000F00158034C03CC034C0084 -:1026200058007000E000C001C00140034C035C038F -:102630004C034801F0004000400000000000000092 -:10264000000000000E010A0191009100910051006C -:1026500051003A00AE03A00250045004480448045C -:102660004804840284030000000000000000000011 -:102670000000000038006C006C006C006C006C0006 -:102680002C0098071C011A01330133016301E30098 -:10269000C308C6093C07000000000000000000005D -:1026A0000C001C00100010000800040000000000D6 -:1026B000000000000000000000000000000000001A -:1026C000000000000000000000000000000000000A -:1026D0000004000200018000800040004000200053 -:1026E00020002000200020002000200040004000AA -:1026F00080008000000100020004000000000000D3 -:10270000020004000800100010002000200040001B -:1027100040004000400040004000400020002000F9 -:10272000100010000800040002000000000000007B -:1027300000000000000000004000C0004000460C07 -:102740004E0FD001F0015E0F460C400040004000EB -:102750000000000000000000000000000000000079 -:1027600000000000000000000000400040004000A9 -:1027700040004000FE0F400040004000400040008C -:102780000000000000000000000000000000000049 -:102790000000000000000000000000000000000039 -:1027A0000000000000000000000000000000000029 -:1027B0000C001C00100010000800040000000000C5 -:1027C0000000000000000000000000000000000009 -:1027D00000000000FE0700000000000000000000F4 -:1027E00000000000000000000000000000000000E9 -:1027F00000000000000000000000000000000000D9 -:1028000000000000000000000000000000000000C8 -:102810001C001C001C000000000000000000000064 -:102820000004000600020003000100018000800097 -:102830004000400060002000200010001000080050 -:1028400008000C0004000600020000000000000068 -:10285000000000000000F00098010C030C030606C5 -:1028600006060606060606060606060606060C0305 -:102870000C039801F00000000000000000000000C0 -:1028800000000000000040007C006000600060006C -:102890006000600060006000600060006000600038 -:1028A00060006000FC030000000000000000000069 -:1028B000000000000000F800840102030603060384 -:1028C000000300018001C000600020001000080229 -:1028D00004020602FE0300000000000000000000E9 -:1028E0000000000000007800C6008601860180011B -:1028F0008001C00070008001000100030003060396 -:1029000006038601F800000000000000000000003F -:1029100000000000000080018001C001A001A001B2 -:1029200090018801880184018201FE0F80018001ED -:1029300080018001E00700000000000000000000AE -:10294000000000000000FC03040004000400040078 -:102950000400F4008C0104030003000306030603D3 -:1029600082018401F8000000000000000000000067 -:10297000000000000000E00118030C030C0004003C -:102980000600E60116030E060606060606060406FF -:102990000C021803F000000000000000000000001E -:1029A000000000000000F8070C060402040100010A -:1029B0000001800080004000400040006000600096 -:1029C00060006000600000000000000000000000E7 -:1029D000000000000000F8010C03060606060606CB -:1029E0000C021C03F000C8010C03060606060606CE -:1029F00006060C03F00100000000000000000000CB -:102A0000000000000000F0000C010C0306020606A6 -:102A10000606060606078C06780600060003000375 -:102A20000C018C0178000000000000000000000094 -:102A30000000000000000000000000000000000096 -:102A4000E000E000E00000000000000000000000E6 -:102A5000E000E000E00000000000000000000000D6 -:102A60000000000000000000000000000000000066 -:102A70006000600000000000000000000000000096 -:102A80000000600060004000200020000000000006 -:102A9000000000000004000200018000400020004F -:102AA0001000080004000800100020004000800012 -:102AB000000100020004000000000000000000000F -:102AC0000000000000000000000000000000000006 -:102AD000FE07000000000000FE07000000000000EC -:102AE00000000000000000000000000000000000E6 -:102AF00000000000040008001000200040008000DA -:102B000000010002000400020001800040002000DB -:102B10001000080004000000000000000000000099 -:102B2000000000000000E0031806040C040C0C0C6C -:102B30000C0C000780014000400040000000000035 -:102B4000E000E000E00000000000000000000000E5 -:102B500000000000E00018030C02CC0564056605C7 -:102B6000A605B604B604B604B604B602E4010C0425 -:102B70000C021803F000000000000000000000003C -:102B8000000000000000600060005000D0009000D5 -:102B90009000880088010801F8010403040304027E -:102BA000020202060F0F00000000000000000000FB -:102BB000000000000000FE008C030C030C030C035B -:102BC0000C038C01FC000C030C020C060C060C061A -:102BD0000C060C03FE0100000000000000000000D5 -:102BE000000000000000E00318030C060C040404BD -:102BF00006000600060006000600060006040C0497 -:102C00000C021803F00000000000000000000000AB -:102C10000000000000007F008C010C030C030C0678 -:102C20000C060C060C060C060C060C060C060C0317 -:102C30000C038C017F000000000000000000000079 -:102C4000000000000000FF0306030604060406005F -:102C500086008600FE0086008600860006000604C8 -:102C600006040602FF030000000000000000000050 -:102C7000000000000000FF0306030604060406002F -:102C800086008600FE00860086008600060006009C -:102C9000060006001F000000000000000000000009 -:102CA000000000000000F00018010C020C020402F9 -:102CB0000600060006000600C60F060306030C0306 -:102CC0000C031803F00000000000000000000000EA -:102CD0000000000000000F0F0606060606060606A6 -:102CE00006060606FE07060606060606060606068B -:102CF000060606060F0F000000000000000000009E -:102D0000000000000000FC03600060006000600044 -:102D100060006000600060006000600060006000B3 -:102D200060006000FC0300000000000000000000E4 -:102D3000000000000000F807C000C000C000C00094 -:102D4000C000C000C000C000C000C000C000C00083 -:102D5000C000C000C000C60066003C0000000000CB -:102D6000000000000000CF038601C60046002600D8 -:102D7000160036002E006E004600C6008600860152 -:102D8000060106038F07000000000000000000009D -:102D90000000000000001F000600060006000600FC -:102DA00006000600060006000600060006000604EF -:102DB00006040602FF0300000000000000000000FF -:102DC0000000000000000707860386038E038E03C1 -:102DD0004E034E034A035A035A033A0332033203A3 -:102DE000320312038707000000000000000000000B -:102DF0000000000000008E0F0C021C021C023402B6 -:102E00003402640264024402C40284028403840320 -:102E1000040304031F020000000000000000000083 -:102E2000000000000000F00098010C030C020606F0 -:102E300006060606060606060606060606060C0230 -:102E40000C039801F00000000000000000000000EA -:102E5000000000000000FF00060306060606060646 -:102E6000060606068603FE000600060006000600AB -:102E7000060006001F000000000000000000000027 -:102E8000000000000000F00098010C030C02060690 -:102E900006060606060606060606060676064C0220 -:102EA000CC039801F0008007000300000000000040 -:102EB000000000000000FF010603060606060606E5 -:102EC00006060603FE004600C600860086010603CD -:102ED000060306060F0E00000000000000000000C0 -:102EE000000000000000F8020C03060206020600C3 -:102EF0000E003C00F800E003800300070206020613 -:102F000006060C03F00100000000000000000000B5 -:102F1000000000000000FE07620461086108600014 -:102F200060006000600060006000600060006000A1 -:102F300060006000F80100000000000000000000D8 -:102F40000000000000001E070C020C020C020C0224 -:102F50000C020C020C020C020C020C020C020C0201 -:102F60000C021801F000000000000000000000004A -:102F70000000000000000F070602040104010C011C -:102F80000C018800880098009800500050007000E4 -:102F900030002000200000000000000000000000C1 -:102FA000000000000000F70E6204420446044604DC -:102FB00064026402E402E4029C029C01980198010C -:102FC0008801880088000000000000000000000068 -:102FD0000000000000009E070C010801180190008D -:102FE000B0006000200060006000D0009000880108 -:102FF000080104038E07000000000000000000002C -:103000000000000000000F0F060404020C0208017B -:103010001801B800B000700060006000600060003F -:1030200060006000F80100000000000000000000E7 -:10303000000000000000FC070C02060302018001F2 -:10304000800040004000200020001000180008040C -:103050000C040402FE030000000000000000000059 -:10306000E00320002000200020002000200020009D -:103070002000200020002000200020002000200050 -:103080002000200020002000E003000000000000DD -:1030900000000000040004000800080010001000F8 -:1030A00010002000200040004000C0008000800090 -:1030B0000001000100020002000200040000000004 -:1030C0007C004000400040004000400040004000C4 -:1030D00040004000400040004000400040004000F0 -:1030E00040004000400040007C0000000000600004 -:1030F0009000080100000000000000000000000037 -:1031000000000000000000000000000000000000BF -:1031100000000000000000000000000000000000AF -:10312000000000000000000000000000000000009F -:10313000000000000000000000000000000000008F -:1031400000000000000000000000FF0F0000000071 -:1031500018006000000000000000000000000000F7 -:10316000000000000000000000000000000000005F -:10317000000000000000000000000000000000004F -:10318000000000000000000000000000000000003F -:10319000F0010C030C030003E0031C030E03060301 -:1031A00006038E0B7C0E00000000000000000000F3 -:1031B0000000000008000E000C000C000C000C00C9 -:1031C000CC013C031C060C060C060C060C060C0677 -:1031D0000C021C03E40100000000000000000000DD -:1031E00000000000000000000000000000000000DF -:1031F000F0008C018C018601060006000600060224 -:103200000C020C01F00000000000000000000000B3 -:10321000000000000002C0030003000300030003DD -:1032200078038C030C030603060306030603060358 -:1032300004038C077801000000000000000000007B -:10324000000000000000000000000000000000007E -:10325000E001180308020C060C06FC070C000C0029 -:1032600018041802E0010000000000000000000047 -:10327000000000000000C00360063006300030008F -:10328000FE013000300030003000300030003000EF -:1032900030003000FC0100000000000000000000D1 -:1032A000000000000000000000000000000000001E -:1032B000F007D8068C018C018C019801F8000C00F5 -:1032C000FC00CC03060306038E03F8000000000098 -:1032D0000000000008000E000C000C000C000C00A8 -:1032E000EC011C030C030C030C030C030C030C0378 -:1032F0000C030C039E07000000000000000000000B -:1033000000000000000060006000000000004000BD -:103310007C00600060006000600060006000600091 -:1033200060006000FC0300000000000000000000DE -:10333000000000000000C001C0010000000000010A -:10334000F001800180018001800180018001800105 -:103350008001800180018001CC007C000000000021 -:103360000000000008000E000C000C000C000C0017 -:103370008C038C008C004C006C005C008C008C0179 -:103380000C010C039E07000000000000000000007C -:103390000000000040007C006000600060006000F1 -:1033A000600060006000600060006000600060001D -:1033B00060006000FC03000000000000000000004E -:1033C00000000000000000000000000000000000FD -:1033D0003707EE0666066606660666066606660633 -:1033E00066066606FF0F00000000000000000000F7 -:1033F00000000000000000000000000000000000CD -:10340000EE011C030C030C030C030C030C030C0354 -:103410000C030C039E0700000000000000000000E9 -:10342000000000000000000000000000000000009C -:10343000F00098010C0306060606060606060606B8 -:103440000C030C03F000000000000000000000006E -:10345000000000000000000000000000000000006C -:10346000EE011C030C060C060C060C060C060C06E2 -:103470000C031C03EC010C000C003E0000000000DB -:10348000000000000000000000000000000000003C -:1034900078028C030C0306030603060306030603E7 -:1034A00004038C03780300030003C007000000003E -:1034B000000000000000000000000000000000000C -:1034C0009F03580638061800180018001800180046 -:1034D00018001800FF0000000000000000000000BD -:1034E00000000000000000000000000000000000DC -:1034F000F0031C030C020C023800F000C0030403AC -:1035000004038C03FC010000000000000000000028 -:10351000000000000000000020002000300030000B -:10352000FE0130003000300030003000300030004C -:1035300030023002E0010000000000000000000046 -:103540000000000000000000000000000000080271 -:103550008E030C030C030C030C030C030C030C0371 -:103560000C039C0778010000000000000000000030 -:10357000000000000000000000000000000000004B -:103580001E070C020801080118019000B000B000ED -:10359000600060002000000000000000000000004B -:1035A000000000000000000000000000000000001B -:1035B000F70E6204460464026402EC029C01980166 -:1035C00098019801080000000000000000000000C1 -:1035D00000000000000000000000000000000000EB -:1035E000BC0718011001B00060006000E00090000E -:1035F000080108039E070000000000000000000012 -:1036000000000000000000000000000000000000BA -:103610009E0708010801080190009000B0006000BA -:10362000600060002000200024001C00000000005A -:10363000000000000000000000000000000000008A -:10364000FC018401C4004400600020003000180226 -:1036500008020C03FC010000000000000000000054 -:1036600000038000800080008000800080008000D7 -:10367000800040002000400080008000800080002A -:1036800080008000800080000003000040004000B7 -:10369000400040004000400040004000400040002A -:1036A000400040004000400040004000400040001A -:1036B000400040004000400040004000000000008A -:1036C0000C0010001000100010001000100010007E -:1036D000100020004000200010001000100010001A -:1036E00010001000100010000C00000000001C0072 -:1036F0002204C2048003000000000000000000005B -:1037000000000000000000000000000000000000B9 -:1037100000000000000000000000000000000000A9 -:103720000000000000000000000000000000000099 -:103730000000000000000000000000000000000089 -:1037400000000000000000000000300030003000E9 -:103750003000300020002000200020002000000069 -:103760000000300030000000000000000000D80021 -:10377000D8006C00240012000000000000000000CF -:103780000000000000000000000000000000000039 -:103790000000000000000000000000008400840021 -:1037A0008400FF0184008400C60042004200FF0143 -:1037B0004200420042000000000000000000000043 -:1037C00000002000F80024012401A401280030009A -:1037D0006000A00020012C0124012401F800200039 -:1037E00020000000000000000000000086004900EA -:1037F0004900290029001900D600280128012801C4 -:1038000024012401C20000000000000000000000AC -:10381000000000000C00120012001200EA00460036 -:10382000460025002900390011003201CC000000BB -:103830000000000000000600060004000200010075 -:103840000000000000000000000000000000000078 -:103850000000000000000000000000000000000167 -:103860008000400020002000200010001000100008 -:1038700010001000100020002000200040008000F8 -:103880000001000000000100020004000800080020 -:1038900008001000100010001000100010000800B8 -:1038A0000800080004000200010000000000000001 -:1038B000000000000000200020002603AE0370007E -:1038C0007000AE032603200020000000000000006E -:1038D00000000000000000000000000000001000D8 -:1038E000100010001000FF01100010001000100068 -:1038F00000000000000000000000000000000000C8 -:1039000000000000000000000000000000000000B7 -:103910000000000000000000000006000600040097 -:103920000200010000000000000000000000000094 -:10393000000000000000FE03000000000000000086 -:103940000000000000000000000000000000000077 -:103950000000000000000000000000000000000067 -:10396000000000000000000000000600060000004B -:103970000000000000000002000100018000800043 -:10398000C000400060002000300010001800080057 -:103990000800040004000200000000000000000015 -:1039A000000000007800840084000201020102018E -:1039B000020102010201020184008400780000007B -:1039C00000000000000000000000000010001C00CB -:1039D0001000100010001000100010001000100067 -:1039E000100010007C00000000000000000000003B -:1039F000000000007C008200020102010201800040 -:103A0000400020001000080004010201FE01000037 -:103A10000000000000000000000000003C00420028 -:103A2000820082004000700080000001000102015D -:103A3000020182007C000000000000000000000085 -:103A40000000400040006000500048004800440072 -:103A500042004200FE01400040004000F001000032 -:103A6000000000000000000000000000FC01040055 -:103A700004000400040074008C0000010001020135 -:103A8000020182007C000000000000000000000035 -:103A900000000000F00008010401040002007A00A8 -:103AA0008600020102010201040184007800000086 -:103AB000000000000000000000000000FE01820085 -:103AC000420040002000100010000800080008001C -:103AD00008000800080000000000000000000000CE -:103AE000000000007800840002010201020184004D -:103AF00078008400020102010201840078000000C5 -:103B000000000000000000000000000078008400B9 -:103B1000820002010201020184017801000180009B -:103B2000820042003C000000000000000000000095 -:103B30000000000000000000000030003000000025 -:103B40000000000000000000000030003000000015 -:103B50000000000000000000000000000000000065 -:103B60000000000010000000000000000000000045 -:103B70000000000010001000100010000000000005 -:103B80000000800040002000100008000400020037 -:103B90000400080010002000400080000000000029 -:103BA0000000000000000000000000000000000015 -:103BB0000000FF01000000000000FF010000000005 -:103BC00000000000000000000000000000000000F5 -:103BD00000000200040008001000200040008000E7 -:103BE0004000200010000800040002000000000057 -:103BF00000000000000000000000780084000201C6 -:103C00000601060100018000400020002000200085 -:103C10000000300030000000000000000000000044 -:103C2000000000007800C400F2015901490145017B -:103C300025012501A500D9000201840078000000BB -:103C40000000000000000000000000001000100054 -:103C50002800280028002800440044007C0044007C -:103C600082008200C7010000000000000000000088 -:103C7000000000003F0042004200420022003E00DF -:103C80004200820082008200820042003F00000069 -:103C90000000000000000000000000007801840126 -:103CA0000201020101000100010001000100010107 -:103CB0000201860078000000000000000000000003 -:103CC000000000003F00C200820002010201020168 -:103CD0000201020102010201820042003F000000D5 -:103CE000000000000000000000000000FF00820053 -:103CF0000201420042007E00420042000200020037 -:103D000002018200FF00000000000000000000002F -:103D100000000000FF0082000201420042007E001D -:103D20004200420002000200020002000700000000 -:103D30000000000000000000000000007001880189 -:103D400004010201020002000200820302010201DA -:103D500004010C01F0000000000000000000000061 -:103D600000000000C7018200820082008200820001 -:103D7000FE0082008200820082008200C7010000F3 -:103D8000000000000000000000000000FE00100025 -:103D900010001000100010001000100010001000A3 -:103DA00010001000FE0000000000000000000000F5 -:103DB00000000000FC012000200020002000200066 -:103DC0002000200020002000200020002100110001 -:103DD0000E0000000000000000000000E7014200AB -:103DE0002200220012001A001600220022004200C7 -:103DF00042008200C7010000000000000000000037 -:103E000000000000070002000200020002000200A1 -:103E1000020002000200020002018200FF00000016 -:103E2000000000000000000000000000C701C60004 -:103E3000C600C600AA00AA00AA00AA00AA00920012 -:103E400092009200D7010000000000000000000076 -:103E500000000000C70186008A008A008A009200E4 -:103E60009200A200A200C200C200C20087000000AF -:103E70000000000000000000000000003800C60044 -:103E800082000101010101010101010101010101A2 -:103E90008200C600380000000000000000000000A2 -:103EA000000000007F008200020102010201820086 -:103EB0007E00020002000200020002000700000073 -:103EC0000000000000000000000000003800C600F4 -:103ED000820001010101010101010101010119013A -:103EE000A600A60078004001C0000000000000000D -:103EF000000000003F0042008200820042003E00BD -:103F000012002200220042004200820087010000CD -:103F100000000000000000000000000078018401A3 -:103F20000201020002000C0070008000000102018A -:103F3000020186007A00000000000000000000007E -:103F400000000000FE00110111011000100010001F -:103F500010001000100010001000100038000000C9 -:103F6000000000000000000000000000C701820007 -:103F70008200820082008200820082008200820031 -:103F80008200440038000000000000000000000033 -:103F900000000000C7018200820044004400440089 -:103FA00044002800280028003800100010000000FD -:103FB000000000000000000000000000BB019200B3 -:103FC000920092009200AA00AA00AA006A0044008F -:103FD0004400440044000000000000000000000015 -:103FE00000000000CE01840044004800280030009A -:103FF000100030002800480048008400CE01000076 -:10400000000000000000000000000000C701820066 -:104010004400440028002800100010001000100088 -:104020001000100038000000000000000000000038 -:1040300000000000FC0184008200400040002000DD -:10404000100010000800080004018400FE000000B9 -:10405000000000000000F00110001000100010002F -:1040600010001000100010001000100010001000D0 -:10407000100010001000F00100000000000000001F -:1040800002000400040008000800080010001000EE -:1040900020002000200040004000800080008000C0 -:1040A0000001000000003E00200020002000200051 -:1040B0002000200020002000200020002000200000 -:1040C0002000200020003E0000000000000038001A -:1040D0002800440000000000000000000000000074 -:1040E00000000000000000000000000000000000D0 -:1040F00000000000000000000000000000000000C0 -:1041000000000000000000000000000000000000AF -:1041100000000000000000000000FF030000180085 -:10412000200000000000000000000000000000006F -:10413000000000000000000000000000000000007F -:10414000000000000000000000000000000000006F -:10415000000000007C0082008200F0008C008200E1 -:104160008200C202BC03000000000000000000004A -:104170000000000003000200020002003A004600B6 -:104180008200820082008200820046003A00000025 -:10419000000000000000000000000000000000001F -:1041A000000000007800840082000200020002008B -:1041B0000201840078000000000000000000000000 -:1041C00000000000C000800080008000B800C40033 -:1041D00082008200820082008200C400B8010000D8 -:1041E00000000000000000000000000000000000CF -:1041F00000000000780084000201FE0102000200BD -:1042000002018400780000000000000000000000AF -:1042100000000000E001100210001000FC0010007F -:10422000100010001000100010001000FC00000032 -:10423000000000000000000000000000000000007E -:1042400000000000F80184008400840084007800ED -:1042500004007C00840102010201FC000000000057 -:104260000000000003000200020002007A00860045 -:10427000820082008200820082008200C70100006A -:1042800000000000000000000000000018001800FE -:10429000000000001C0010001000100010001000B2 -:1042A000100010007C000000000000000000000072 -:1042B000000000006000600000000000700040008E -:1042C00040004000400040004000400040004000EE -:1042D00022001E0000000000000000000300020099 -:1042E00002000200E200220012000A001600220072 -:1042F00042008200C7010000000000000000000032 -:10430000000000001E00100010001000100010003F -:10431000100010001000100010001000FE0000003F -:10432000000000000000000000000000000000008D -:10433000000000007F009200920092009200920024 -:1043400092009200B7010000000000000000000091 -:104350000000000000000000000000007B0086005C -:10436000820082008200820082008200C701000079 -:10437000000000000000000000000000000000003D -:104380000000000078008400020102010201020125 -:10439000020184007800000000000000000000001E -:1043A0000000000000000000000000003B0046008C -:1043B0008200820082008200820046003A000200F1 -:1043C00002000700000000000000000000000000E4 -:1043D00000000000B800C400820082008200820059 -:1043E0008200C400B80080008000C001000000000E -:1043F000000000000000000000000000CE012801C5 -:104400001800080008000800080008003E0000002E -:10441000000000000000000000000000000000009C -:1044200000000000BC00C200820006003800C0008E -:10443000820086007A0000000000000000000000FA -:10444000000000000000100010001000FC00100030 -:10445000100010001000100010009000600000001C -:10446000000000000000000000000000000000004C -:1044700000000000C30082008200820082008200EF -:104480008200C200BC01000000000000000000002B -:10449000000000000000000000000000C7018200D2 -:1044A00044004400440028002800100010000000D0 -:1044B00000000000000000000000000000000000FC -:1044C00000000000BB01920092009200AA00AA0026 -:1044D0004400440044000000000000000000000010 -:1044E000000000000000000000000000CE01840079 -:1044F000480030003000300048008400CE01000049 -:1045000000000000000000000000000000000000AB -:1045100000000000EE0184008800480048005000C0 -:10452000300020001000100010000C0000000000FF -:10453000000000000000000000000000FE0042003B -:10454000220020001000080084008200FE0000000D -:1045500000000000000080014000400040004000DA -:10456000400040006000100060004000400040003B -:10457000400040004000400080010000200020007A -:10458000200020002000200020002000200020002B -:10459000200020002000200020002000200020001B -:1045A00020002000000006000800080008000800A5 -:1045B0000800080018002000180008000800080083 -:1045C0000800080008000800060000001C00260281 -:1045D0002203C001000000000000000000000000F5 -:1045E00000000000000000000000000000000000CB -:1045F00000000000000000000000000000000000BB -:104600000000000000000008080808080808000072 -:104610001818000000486C24120000000000000080 -:10462000000000000000002424247F1212127F12D8 -:10463000121200000000081C2A2A0A0C1828282A36 -:104640002A1C080800000022251515152A58545464 -:10465000542200000000000C1212120A76252911C3 -:10466000916E000000060604030000000000000038 -:10467000000000000040201010080808080808107A -:10468000102040000002040808101010101010083C -:10469000080402000000000008086B1C1C6B0808DE -:1046A0000000000000000000080808087F08080853 -:1046B00008000000000000000000000000000000F2 -:1046C000060604030000000000000000FE000000D9 -:1046D00000000000000000000000000000000000DA -:1046E000060600000000804040202010100808044A -:1046F00004020200000000182442424242424242A8 -:1047000024180000000000080E080808080808081F -:10471000083E00000000003C4242422020100804F5 -:10472000427E00000000003C4242201820404042EF -:10473000221C0000000000203028242422227E2099 -:10474000207800000000007E0202021A264040424B -:10475000221C0000000000382402021A26424242B5 -:10476000241800000000007E22221010080808080B -:10477000080800000000003C424242241824424243 -:10478000423C00000000001824424242645840406D -:10479000241C0000000000000000181800000000A9 -:1047A00018180000000000000000000800000000D1 -:1047B000000808040000004020100804020408104B -:1047C000204000000000000000007F0000007F008B -:1047D0000000000000000002040810204020100823 -:1047E000040200000000003C42424640201010003D -:1047F000181800000000001C225A555555552D422E -:10480000221C00000000000808181414243C224256 -:1048100042E700000000001F2222221E22424242E4 -:10482000221F00000000007C424201010101014200 -:10483000221C00000000001F22424242424242422B -:10484000221F00000000003F4212121E12120242FC -:10485000423F00000000003F4212121E12120202EC -:10486000020700000000003C222201010171212208 -:10487000221C0000000000E7424242427E424242C7 -:1048800042E700000000003E080808080808080881 -:10489000083E00000000007C1010101010101010D6 -:1048A0001010110F0000007722120A0E0A121222B5 -:1048B0002277000000000007020202020202020248 -:1048C000427F000000000077363636362A2A2A2A30 -:1048D0002A6B0000000000E346464A4A52525262E8 -:1048E000624700000000001C22414141414141411A -:1048F000221C00000000003F424242423E020202EF -:10490000020700000000001C2241414141414D537B -:10491000321C60000000003F4242423E121222223E -:1049200042C700000000007C4242020418204042BE -:10493000423E00000000007F4908080808080808F7 -:10494000081C0000000000E742424242424242424C -:10495000423C0000000000E74242222424141418C4 -:10496000080800000000006B4949494955553622A6 -:1049700022220000000000E74224241818182424F2 -:1049800042E70000000000772222141408080808FB -:10499000081C00000000007E2120101008040442C2 -:1049A000423F0000007808080808080808080808BE -:1049B000080878000000020204040808081010200B -:1049C00020204040001E1010101010101010101069 -:1049D00010101E000038440000000000000000001D -:1049E00000000000000000000000000000000000C7 -:1049F000000000FF000608000000000000000000AA -:104A000000000000000000000000003C427844422A -:104A100042FC0000000000030202021A2642424249 -:104A2000261A0000000000000000003844020202C4 -:104A30004438000000000060404040784442424258 -:104A400064D80000000000000000003C427E02022A -:104A5000423C0000000000F08808087E08080808B2 -:104A6000083E0000000000000000007C22221C0222 -:104A70003C42423C000000030202023A46424242EB -:104A800042E700000000000C0C00000E08080808B7 -:104A9000083E0000000000303000003820202020B8 -:104AA0002020221E0000000302020272120A1612C7 -:104AB000227700000000000E08080808080808080F -:104AC000083E0000000000000000007F92929292D9 -:104AD00092B70000000000000000003B4642424246 -:104AE00042E70000000000000000003C4242424259 -:104AF000423C0000000000000000001B2642424231 -:104B0000221E0207000000000000007844424242DA -:104B1000447840E000000000000000774C040404EA -:104B2000041F0000000000000000007C42023C4026 -:104B3000423E0000000000000008083E0808080887 -:104B400008300000000000000000006342424242C2 -:104B500062DC000000000000000000E74224241492 -:104B60000808000000000000000000EB494955550E -:104B7000222200000000000000000076241818180F -:104B8000246E000000000000000000E7422424140E -:104B900018080807000000000000007E2210080826 -:104BA000447E000000C02020202020102020202053 -:104BB0002020C00010101010101010101010101035 -:104BC0001010101000060808080808100808080847 -:104BD000080806000C32C2000000000000000000BF -:104BE00000000000000000000000000000000000C5 -:104BF00000000404040404040004000000140A0A71 -:104C00000000000000000000000014143F140A3FE0 -:104C10000A0A000000041E1505060C14150F0400F6 -:104C2000000012150D0A142C2A1200000000040ABC -:104C30000A1E1515093600000002020100000000DE -:104C400000000000002010080808080808102000D4 -:104C50000002040808080808080402000000000414 -:104C6000150E0E150400000000000404041F0404C7 -:104C7000040000000000000000000000000202012B -:104C800000000000001F0000000000000000000005 -:104C900000000000000200000010080808040402E0 -:104CA0000202010000000E1111111111110E00007D -:104CB0000000040604040404040E000000000E11A9 -:104CC00011080402011F000000000E11100C10104A -:104CD000110E00000000080C0A0A091E0818000046 -:104CE00000001F01010F1010110E000000000E093E -:104CF000010F1111110E000000001F090804040427 -:104D00000404000000000E11110E1111110E00001C -:104D100000000E1111111E10120E00000000000004 -:104D20000400000000040000000000000004000077 -:104D300000040400002010080402040810200000F1 -:104D4000000000001F00001F000000000002040817 -:104D5000102010080402000000000E1111080404C5 -:104D60000004000000000E111915151D011E0000A1 -:104D7000000004040C0A0A1E1233000000000F1287 -:104D8000120E1212120F000000001E11010101018B -:104D9000110E000000000F1212121212120F00006A -:104DA00000001F120A0E0A02121F000000001F124C -:104DB0000A0E0A020207000000001C12010139114C -:104DC000120C000000003312121E121212330000E7 -:104DD00000001F0404040404041F000000003E0837 -:104DE0000808080808090700000037120A060A0A1E -:104DF000123700000000070202020202223F0000F8 -:104E000000001B1B1B1B15151515000000003B1295 -:104E100016161A1A1217000000000E1111111111A6 -:104E2000110E000000000F12120E02020207000015 -:104E300000000E1111111117190E180000000F12A9 -:104E4000120E0A121237000000001E11010608108F -:104E5000110F000000001F1504040404040E0000DC -:104E60000000331212121212120C00000000331252 -:104E7000120A0A0C0404000000001515150E0A0A97 -:104E80000A0A000000001B0A0A04040A0A1B0000A8 -:104E900000001B0A0A040404040E000000001F099D -:104EA00008040402121F0000001C0404040404048B -:104EB00004041C0000020202040408080810000098 -:104EC000000E08080808080808080E0000040A0078 -:104ED00000000000000000000000000000000000D2 -:104EE0000000003F0004000000000000000000007F -:104EF00000000000000C121C123C00000000030225 -:104F0000020E1212120E000000000000001C12021D -:104F1000021C000000001810101C1212123C0000AD -:104F200000000000000C121E021C000000003804EB -:104F3000041E0404041E000000000000003C120CCB -:104F4000021E221C00000302020E12121237000081 -:104F50000000040000060404040E00000000080025 -:104F6000000C08080808080700000302023A0A0EAD -:104F7000123700000000070404040404041F0000AA -:104F800000000000000F15151515000000000000BE -:104F9000000F12121237000000000000000C121265 -:104FA000120C000000000000000F1212120E020787 -:104FB00000000000001C1212121C1038000000003B -:104FC000001B06020207000000000000001E020C89 -:104FD000101E000000000004040E04040418000069 -:104FE00000000000001B1212123C00000000000034 -:104FF0000037120A0C040000000000000015150E16 -:105000000A0A000000000000001B0A040A1B00003E -:10501000000000000037120A0C0404030000000026 -:10502000001E0804041E00000018080808040808F0 -:1050300008081800080808080808080808080808E8 -:1050400000060404040804040404060002251800F1 -:1050500000000000000000006C65747465720000C0 -:1050600064656661756C7420757365720073657430 -:105070005661720073657420766172007570006409 -:105080006F776E007269676874006C65667400748F -:105090006162006261636B7370616365006261638A -:1050A0006B73706163650064656C65746500656E43 -:1050B00074657200656E7465720068656C7000736B -:1050C000686F7720636F6D6D616E6420696E666FC7 -:1050D0000D0A68656C70205B636D645D00757365B7 -:1050E0007273006C69737420616C6C2075736572E7 -:1050F00000636D6473006C69737420616C6C206371 -:105100006D640076617273006C69737420616C6CFD -:1051100020766172006B657973006C69737420612D -:105120006C6C206B657900636C65617200636C6503 -:10513000617220636F6E736F6C65000064656661F9 -:10514000756C745461736B000D0A436F6D6D616E05 -:1051500064204C6973743A0D0A0000000D0A566110 -:1051600072204C6973743A0D0A0000000D0A5573E1 -:105170006572204C6973743A0D0A00000D0A4B6584 -:1051800079204C6973743A0D0A000000436F6D6D0D -:10519000616E64206E6F7420466F756E640D0A0038 -:1051A0000D0A5761726E696E673A20436F6D6D61CB -:1051B0006E6420697320746F6F206C6F6E670D0AC8 -:1051C00000000000206973206E6F742061207661FA -:1051D000720D0A0063616E27742073657420726516 -:1051E0006164206F6E6C79207661720D0A00000098 -:1051F00063616E27742073657420706F696E7465C7 -:10520000720D0A000D0A205F20202020202020207F -:10521000205F2020205F2020202020202020202010 -:1052200020202020202020205F202020202020203F -:105230002020205F205F200D0A7C207C2020202061 -:105240005F5F5F7C207C5F7C207C5F205F5F5F20F6 -:105250005F205F5F2020205F5F5F7C207C5F5F209E -:1052600020205F5F5F7C207C207C0D0A7C207C20DE -:1052700020202F205F205C205F5F7C205F5F2F203D -:105280005F205C20275F5F7C202F205F5F7C2027D2 -:105290005F205C202F205F205C207C207C0D0A7C1E -:1052A000207C5F5F7C20205F5F2F207C5F7C207CE8 -:1052B0007C20205F5F2F207C202020205C5F5F20EF -:1052C0005C207C207C207C20205F5F2F207C207C49 -:1052D0000D0A7C5F5F5F5F5F5C5F5F5F7C5C5F5F51 -:1052E0007C5C5F5F5C5F5F5F7C5F7C202020207C5C -:1052F0005F5F5F2F5F7C207C5F7C5C5F5F5F7C5FBC -:105300007C5F7C0D0A0D0A4275696C643A2020208E -:10531000202020205365702031302032303235205B -:1053200030303A34333A34340D0A56657273696F4B -:105330006E3A2020202020332E322E340D0A436F67 -:10534000707972696768743A2020202863292032B6 -:10535000303230204C65747465720D0A0000000014 -:105360000D0A70617373776F7264206572726F7269 -:105370000D0A0000566172206E6F7420466F756EC4 -:10538000740D0A001B5B324B0D000000434D44209E -:105390000000000056415220000000004B455920FB -:1053A00000000000636F6D6D616E642068656C7055 -:1053B000206F662000000000506C656173652069F5 -:1053C0006E7075742070617373776F72643A000049 -:1053D0004E4F4E45000000001B5B324A1B5B3148BC -:1053E0000000000055534552000000003C550108E4 -:1053F000000000209802000054080008CC56010864 -:105400009802002018170100288F0008CC560108C8 -:1054100000C0012000400000288F000800080000A4 -:10542000585001085F500108605001080021000039 -:105430006D500108C1C50008745001080009000042 -:1054400000415B1BA7CA00087C500108000900004E -:1054500000425B1B91B700087F5001080019000053 -:1054600000435B1B1BC400088450010800190000A6 -:1054700000445B1B07C100088A50010800090000B6 -:1054800000000009E5C800088F500108001900005D -:1054900000000008A1B500089350010800190000A1 -:1054A0000000007FA1B500089D5001080019000010 -:1054B0007E335B1B87B60008A75001080019000067 -:1054C0000000000AA1B70008AE5001080019000052 -:1054D0000000000DA1B70008B45001080020000032 -:1054E000BA500108F5BD0008BF50010800210000B6 -:1054F000DD500108B5CA0008E35001080021000092 -:10550000F150010875B60008F650010800210000AE -:1055100003510108C7CA0008085101080021000012 -:1055200015510108F5C000081A51010800210000BA -:105530002751010831B600082D510108813210426F -:1055400001035D24F41AAA0101141345A8140831BB -:10555000A914088045122016C0012080C51C208097 -:10556000E50C6998B11334E813080C120C121812E8 -:10557000141314EA1B0810BE1A200C1394EC1A081A -:1055800012111A3C041344F11B081822124812414C -:105590001E8C03010820221A80181C8C0D01301269 -:1055A0002032401C4C250148121832301E1C370195 -:1055B000080A2032281EF4450108085432101EE45F -:1055C0004B0108066C720C13FD6C1408456D1B082A -:1055D00055041A81041AC1041AC9141A0D081312A9 -:1055E00001140202021640830440571D0201020307 -:1055F000B9071A040309041A0313E9091B08E5048F -:105600001AA104130D0A1B08310441130A063202C1 -:105610002A40FC13AD671408A9654C08F7691C13F0 -:105620007D6614089D641B086114C11A21281ADDC7 -:105630001C1A69081ACD081C090243871125C032BB -:1056400009041B01020B1305241610010524011087 -:105650000901042402020524061E0107058203ED48 -:105660001B0904BD320A2E0705010240072A8107E3 -:105670001C810182C41809520108A0510108480484 -:105680001A5C041A6C041A7C041A8C041AF0041AAA -:10569000D4041AC4041E74530108A4041AB8041ACA -:1056A00060041AD8041A84041A8C041A94041AE4A4 -:1056B000041A9C041AD004E3222213E0E71B08E634 -:0C56C0000417C6E533B4FD960200080094 +:100000004FF0080B0120009005E04FF0020B02209A +:10001000009000E000BF00BF00982918701C08B9CC +:10002000012000E000200C1811E020782E2803D1D8 +:100030004FF00108641C0AE0207800F025F907FB66 +:100040000B0708EB88004FEA4008641C00BF2078CB +:100050000028EAD1BAF1040F17D1B8F1000F14D07B +:1000600000EE107AB8EE401A00EE108AB8EE400AA0 +:10007000C1EE000A00EE106AB8EEC00A20EE800A57 +:1000800010EE109A4846BDE8F88F07FB06F0FAE735 +:10009000000000002DE9F04107460C4616461D46BB +:1000A00026B1207824282FD1607868B320782728BB +:1000B00008D1607830B12046FFF74CFF286000205F +:1000C000BDE8F08120782D2805D02078302808DB85 +:1000D0002078392805DC2046FFF766FF28600020DD +:1000E000EEE72078242807D1607828B12A462146F7 +:1000F000384600F031F8E3E7207828B1204600F0D8 +:1001000006F828600020DBE74FF0FF30D8E770B535 +:100110000446254600262078222802D1601C044689 +:10012000054613E028785C2805D12846FFF712FF22 +:10013000A0556D1C07E02878222802D10020A05588 +:1001400001E02878A0556D1C701C86B22878002824 +:10015000E8D1A055204670BD2DE9F04104460D467A +:1001600016460023691C2046A26D00F028FD0746B4 +:100170003FB13946204600F0FDF830600020BDE870 +:10018000F0814FF0FF30FAE72DE9F0478CB0804660 +:100190000C4615461E464FF0000A202104A8F0F731 +:1001A000FAF8A07800F00F01681E814203DDA07804 +:1001B00000F00F0000E0681E07464FF0000912E053 +:1001C00004A800EB890309F1010056F82010002271 +:1001D0004046FFF75FFF20B14FF0FF300CB0BDE8A5 +:1001E000F08709F10109681E4845E9DC082F45D26E +:1001F000DFE807F004080E151C232C37A0688047A1 +:1002000082463EE0D4F808900498C847824638E019 +:10021000D4F80890DDE90401C847824631E0D4F8FB +:10022000089004A807C8C84782462AE0D4F8089076 +:1002300004A80FC8C847824623E0D4F8089008985D +:10024000009004A80FC8C84782461AE0D4F8089066 +:10025000DDE90801CDE9000104A80FC8C8478246BE +:100260000FE0D4F80890DDE908120A98CDE90012F1 +:10027000029004A80FC8C847824602E04FF0FF3A38 +:1002800000BF00BF5046A9E70146302905DB3929E8 +:1002900003DCA1F13000C0B27047612905DB66299B +:1002A00003DCA1F15700C0B2F6E7412905DB46297E +:1002B00003DCA1F13700C0B2EEE70020ECE7014615 +:1002C000487800F00F00012801DCC86870474878C2 +:1002D00000F00F00072801DCC868F7E7487800F055 +:1002E0000F00082801DCC868F0E7C868EEE70000E6 +:1002F00010B50446002004E03021104A1154411C7E +:10030000C8B20928F8DB607800F00F00012801DC92 +:10031000606810BD607800F00F00072801DC60689D +:10032000F7E7607800F00F00082801DC6068F0E76C +:100330000249606800F005FF0048EAE74C2401200C +:10034000002111E00A4850F8210058B1084850F83F +:10035000210090F86000C0F3400018B1044850F844 +:1003600021007047481C01B20529EBDB0020F8E7AB +:10037000382401202DE9F04107460C46002660781C +:1003800000F00F00801E06281BD2DFE800F00306F5 +:100390000A0D0E10A068066814E0A068B0F90060AD +:1003A00010E0A06806780DE000BFA6680AE0A0682B +:1003B00045681DB1A1680868A84700E0002006460E +:1003C00000E000BF00BF3046BDE8F0812DE9F047F6 +:1003D00004468846B8F1000F01D1BDE8F0872046F9 +:1003E000E16E884718274FF00009208F00F47F4006 +:1003F00018B100276FF0FF090EE0A06B00F47F003A +:1004000018B10827DFF8BC9006E0A06B00F07F4031 +:1004100010B110274FF07F49A66D00253EE006EB96 +:100420000510407800F00F00092835D106EB0511C2 +:100430002046FFF749FC70BB06EB0510406800EA58 +:100440000900A16B884227D106EB05104168FF2007 +:10045000B840084008FA07F188421DD108FA07F1B0 +:10046000A06B0843A0634FF0000847B106EB0510EE +:100470004068A7F10801FF228A40104058B906EBF6 +:100480000510806820B106EB05108168204688477A +:100490000021A16306E0FFE7681C05B25C20005B59 +:1004A000A842BCDC00BFB8F1000F05D00021A16359 +:1004B0004146204600F0CCFA2046216F884700BF15 +:1004C0008BE700000000FFFF70B504460D46FFF704 +:1004D00037FF064606B970BD012C03D1304600F047 +:1004E00089F905E0012C03DD3046696800F094FECF +:1004F00000BFF0E770B504460D46002D25DDB4F9C8 +:1005000054105420005B401E02B25420025350206D +:10051000025B5220005B824202DD5020005B01E062 +:100520005220005B404281421DDC5020015B522082 +:10053000005B814202DD5020005B01E05220005B45 +:10054000404201B2542001530DE0002D0ADA54203C +:10055000005B401C01B254200153002903DD00213F +:10056000015370BDFDE72046FFF7DAFB5420005B26 +:1005700018B90021A181E1811BE05220005B401DE0 +:10058000B4F954100844052190FBF1F201FB12016B +:1005900004F13C0050F821603146206900F000FD74 +:1005A000A08100B9DDE7A189E1812046216900F041 +:1005B000E3FE00BFD5E710B50446002154200153E7 +:1005C0005020005B002810DD5222125B21690AB91D +:1005D000052201E05222125B521E04F13C0353F843 +:1005E0002200EFF7EAFE00B910BD5222135B04F1BE +:1005F0003C0252F82300216900F0D2FC28B15220BD +:10060000005B401C81B2522001535020005B401C13 +:1006100081B250200153052901DD052101535220EB +:10062000005B052802DB00215220015300BFDBE7FD +:100630002DE9F04104460D4616460020A081002118 +:10064000E181206094F8600020F00100401C84F8F3 +:1006500060002561062096FBF0F0A086542001532F +:100660005020015352200153002009E0A28E411C6A +:1006700002FB015204F13C0141F82020411C08B268 +:100680000528F3DB0E48A0650E480D49401AC0F35B +:100690000F115C2001532046FFF7D8FA00230AA16E +:1006A0002046A26D00F08BFA07463946204600F03E +:1006B000C3FA0121204600F0E5FDBDE8F08100000D +:1006C0006C6101088C6201086C65747465720000CD +:1006D00070B504460D46A189A08E401E81420DDBF7 +:1006E00038484168204600F047FE0121204600F0CE +:1006F000C9FD2046216900F03FFE70BDE089A18957 +:10070000884218D1A189481CA08120694554002144 +:10071000A28920698154E089401CE08194F860003E +:1007200000F0010008B1284600E02A2001462046DA +:1007300000F03CFD44E0E089A189884240DAA289CA +:10074000E189511A08B20AE0E1890144491E22698F +:10075000525CE189014423695A54411E08B20028C1 +:10076000F2DCE189481CE081206945540021A08920 +:10077000401C80B22269A0811154E089401E06B25B +:100780000EE094F8600000F0010010B12069805D77 +:1007900000E02A200146204600F008FD701C06B249 +:1007A000A089B042EDDCA189E089081A06B205E013 +:1007B0000821204600F0FAFC701E06B2002EF7DC7D +:1007C00000BF9AE7D801002010B5FFF7B9FD044635 +:1007D00014B1204600F0B8F810BD10B50446E08909 +:1007E000002806DD0821204600F0E0FCE089401EDC +:1007F000E08110BD10B50446204600F001F810BDA0 +:1008000070B50546AE6D10488168284600F0B4FD0D +:10081000002413E006EB0410407800F00F000128DC +:100820000ADC06EB04112846FFF74EFA20B906EB66 +:100830000411284600F00AF8601C04B25C20405BFA +:10084000A042E7DC70BD0000D80100202DE9F04196 +:1008500007460C462046FFF74BFD0546294638461D +:1008600000F08AFDC0F1160006B2002E01DD304610 +:1008700000E00420064600BF2021384600F096FC28 +:10088000701E00B2061EF7D1607800F00F0001283C +:1008900005DC2A48016C384600F06EFD25E06078E2 +:1008A00000F00F00072805DC2448416C384600F0B2 +:1008B00063FD1AE0607800F00F00082805DC1F488F +:1008C000816C384600F058FD0FE0607800F00F00B2 +:1008D000092805DC1948C16C384600F04DFD04E0DC +:1008E0001648016D384600F047FD15A1384600F066 +:1008F00043FD07250DE020780122AA40104008B1F1 +:10090000782000E02D200146384600F04FFC681E9C +:1009100045B2002DEFDA0AA1384600F02DFD204641 +:10092000FFF7CDFC05462946384600F047FC05A1F7 +:10093000384600F021FDBDE8F0810000D80100201C +:10094000202000000D0A000070B50646B56D134862 +:100950004169304600F010FD00241AE005EB041058 +:10096000407800F00F00082811DD05EB04104078F6 +:1009700000F00F0009280ADC05EB04113046FFF7F0 +:10098000A3F920B905EB04113046FFF75FFF601CA7 +:1009900004B25C20805BA042E0DC70BDD801002086 +:1009A00070B50646B56D13480169304600F0E4FCA9 +:1009B00000241AE005EB0410407800F00F0007282F +:1009C00011DD05EB0410407800F00F0008280ADC68 +:1009D00005EB04113046FFF777F920B905EB041158 +:1009E0003046FFF733FF601C04B25C20805BA042FE +:1009F000E0DC70BDD801002070B50646B56D134827 +:100A0000C168304600F0B8FC00241AE005EB041081 +:100A1000407800F00F00012811DD05EB041040784C +:100A200000F00F0007280ADC05EB04113046FFF741 +:100A30004BF920B905EB04113046FFF707FF601CA6 +:100A400004B25C20805BA042E0DC70BDD8010020D5 +:100A500070B504460D4694F8600020F0040084F858 +:100A6000600029462046FFF733FE70BD18B50446E6 +:100A700008200090A189202304F11402206900F0CD +:100A8000EDF9E08618BD70B5044600252BE004F1B1 +:100A9000140050F82500007822280CD1002104F120 +:100AA000140050F82500017004F1140050F82510CE +:100AB000491C40F8251004F1140151F82500EFF706 +:100AC00075FC86B204F1140050F82510701E085C05 +:100AD000222806D1002104F1140050F82520701EB0 +:100AE0001154681C85B2E08EA842D0DC70BD10B5F0 +:100AF0000446E089A189884207DAE289501CE08136 +:100B00002069815C204600F051FB10BD2DE9F041C9 +:100B100004460D46002694F8600020F00200801C78 +:100B200084F86000687800F00F0088B92046FFF76D +:100B3000AAFFAF68E08E04F11401B8470646687852 +:100B4000C0F3401018B93146204600F0CFFB2DE02D +:100B5000687800F00F00012810D1E28E04F1140330 +:100B600029462046FFF710FB06466878C0F3401080 +:100B7000E0B93146204600F0B9FB17E0687800F094 +:100B80000F00022809DB687800F00F00072804DC5A +:100B90002946204600F002F908E0687800F00F00CE +:100BA000082803D12946204600F046F894F8600052 +:100BB00020F0020084F860003046BDE8F0812DE9A5 +:100BC000F0470646884614461F465C20805BB16DA0 +:100BD000611AA0EB11101FFA80F9002528E004EB40 +:100BE0000510407800F00F00092805D004EB05112E +:100BF0003046FFF769F800B118E004EB0510FFF785 +:100C000077FB824647B951464046EFF7D6FB60B9BD +:100C100004EB0510BDE8F0873A4651464046EFF731 +:100C2000E3FB10B904EB0510F4E700BF681C85B2C4 +:100C30004D45D4DB0020EDE770B504460D46256038 +:100C4000A86858B1A868EFF7B1FB38B1E08E022868 +:100C500006DBA169A868EFF7B0FB08B9012000E046 +:100C6000002094F8601060F3000184F860100848D8 +:100C7000816B204600F080FB94F8600000F00100DA +:100C800020B103480168204600F076FB70BD0000EB +:100C9000D80100202DE9F04106460F46FFF750FB32 +:100CA000054615B90020BDE8F081002331462846ED +:100CB000AA6DFFF784FF044634B91148816A2846BB +:100CC00000F05AFB0020EEE7607800F00F000228E9 +:100CD00004DB607800F00F0007280ADD3146284663 +:100CE00000F04AFB0648416A284600F045FB002018 +:100CF000D9E73A462146284600F004F8D3E7000039 +:100D0000D80100202DE9F04106460C4615466078D2 +:100D1000C0F3801028B12048016A304600F02CFB57 +:100D200034E0607800F00F00801E06282CD2DFE847 +:100D300000F003060A0D1218A068056025E029B22C +:100D4000A068018021E0A06805701EE02946A06827 +:100D500000F026F919E01048C169304600F00CFB9C +:100D600013E0A068806870B1A068006830B1A06826 +:100D70008768A16808682946B84704E0A0688768C2 +:100D80002846B84700BF00E000BF00BF21463046FC +:100D900000F004F8BDE8F081D8010020FEB505465A +:100DA0000C4626A207CA8DE8070021462846FFF711 +:100DB000E1FA07462846616800F0DEFA22A12846DB +:100DC00000F0DAFA607800F00F0005280CD11FA1BE +:100DD000284600F0D1FA3946284600F0CDFA1BA18A +:100DE000284600F0C9FA21E06946384600F07EF94D +:100DF000C0F10B00694646183146284600F0BCFA9F +:100E000013A1284600F0B8FA002004E030210DF8C4 +:100E10000010411C08B20B28F8DB6946384600F088 +:100E200090F96946284600F0A7FA00BF00BF0AA162 +:100E3000284600F0A1FA3846FEBD000030303030C0 +:100E40003030303030303000203D200022000000B3 +:100E50002C203078000000000D0A00002DE9FF4F23 +:100E600004468C4615460D9F4FF001080020009067 +:100E70000190029003900021002600BF04E00022B0 +:100E800045F82020421C10B2B842F8DB002068E090 +:100E900011BB225C9A420DD0B8F1010F0AD1BE42BB +:100EA00008DA04EB000A3246761C45F822A04FF01F +:100EB000000811E0225C9A4202D0225C202A0BD169 +:100EC000B8F1000F08D100222254421CA25C202A53 +:100ED00001D04FF0010842E0002234E0002918DD83 +:100EE00014F80090DFF888A00AEB420A9AF801A0F3 +:100EF000D1450ED1A1F101091DF80990DFF870A0CC +:100F00001AF812A0D14504D1A1F1010909F0FF019D +:100F10001BE014F80090DFF858A01AF812A0D14591 +:100F20000DD1DFF84C9019F812B0894601F1010A91 +:100F30000AF0FF010DF809B001F00F0105E002F120 +:100F4000010909F0FF02002AC8D000BF225C5C2A18 +:100F500004D1421CA25C0AB1421C90B200BF421CE8 +:100F600090B2604594DB304604B0BDE8F08F0000DD +:100F70002C02002030B502460B460020002108E07C +:100F8000545C5D5CAC4200D008E0441CA0B24C1C38 +:100F9000A1B2545C14B15C5C002CF1D100BF30BD37 +:100FA0000246002003E00B5C1354431C98B20B5C18 +:100FB000002BF8D1135470472DE9F84F0446B4F8CC +:100FC00034A04FF000080025A08938B92046FFF76B +:100FD00011FC0121204600F055F970E0A08900289D +:100FE0006DDD0021A28920698154A66D002737E0BC +:100FF00006EB07112046FEF767FE78BB06EB0710ED +:10100000FFF776F9834659462069FFF7B3FFA189B8 +:10101000884223D1F5B1012D03D12AA1204600F049 +:10102000ABF906EB08112046FFF710FC06EB0710A2 +:10103000FFF75EF9834606EB0810FFF759F95946AA +:101040000090FFF797FF8146CA4501DD484600E062 +:10105000504682461FFA87F8681C85B2781C07B292 +:101060005C20005BB842C3DC0DB9BDE8F88F012DF0 +:1010700002D12046FEF754FE4DB106EB0810FFF7F3 +:1010800037F9074639462069FFF78AFFA081012D0D +:101090000ADD06EB08112046FFF7D8FB01212046A8 +:1010A00000F0F0F8A4F80CA00021A2892069815476 +:1010B000A189E1812046216900F05EF900BF00BFEF +:1010C000D3E700000D0A000008B505462C460CE0E9 +:1010D000606E50B101216846626E9047012804D1CC +:1010E0009DF800102046FFF771F9F1E730B5024690 +:1010F0000B241346002A00DA53420020C8720DE088 +:101100000A2093FBF0F500FB15303030C5B2601EAD +:10111000C0B204460D540A2093FBF0F3002BEFD12C +:10112000002A04DA2D25601EC0B204460D5422B9EF +:101130003025601EC0B204460D54C4F10B0040B20D +:1011400030BD30B502460B460824002018720EE070 +:1011500002F00F01092902DD01F1570001E001F160 +:101160003000C5B2601EC0B204461D541209002AE8 +:10117000EED1C4F1080040B230BD10B504460121E3 +:101180002046FFF7B7F910BD10B5FFF7D9F80446B0 +:1011900014B12046FFF704FC10BD10B5FFF7D0F8DE +:1011A000044614B12046FFF727FC10BD13B50446D2 +:1011B000012101A8A26E90471CBD00002DE9F0415D +:1011C00004460F4600253E46A06E10B90020BDE83B +:1011D000F08102E0761C681C85B2307828B1307846 +:1011E0000D2802D030780A28F4D1242D08DD2421DE +:1011F0003846A26E9047032106A0A26E904703E0F6 +:1012000029463846A26E9047242D01DD2420DEE7D2 +:101210002720DCE72E2E2E002DE9F04104460E4655 +:10122000002331462046A26DFFF7C9FC0546EDB10B +:101230001248C16A204600F09FF82846FFF758F888 +:1012400007463946204600F097F80DA1204600F0E9 +:1012500093F82846FFF733F807463946204600F052 +:101260008BF807A1204600F087F804E00348816965 +:10127000204600F081F8BDE8F0810000D801002090 +:101280000D0A000070B504460D4694F8600000F0A9 +:101290000100D8B11DB110A1204600F06DF8206802 +:1012A0004168204600F068F80CA1204600F064F880 +:1012B000A06808B1A06800E009A00146204600F03F +:1012C0005BF808A1204600F057F804E00648016BDF +:1012D000204600F051F870BD0D0A00003A000000F1 +:1012E0002F00000024200000D8010020FEB5054694 +:1012F0000C4618A2D2E900109268CDE901020091D3 +:1013000017A1284600F038F869462046FFF7EEFEA0 +:10131000C0F10B00694646183146284600F02CF80B +:1013200012A1284600F028F8002004E030210DF832 +:101330000010411C08B20B28F8DB69462046FFF775 +:1013400000FF6946284600F017F80AA1284600F079 +:1013500013F8FEBD303030303030303030303000B7 +:1013600052657475726E3A20000000002C203078AF +:10137000000000000D0A00002DE9F04104460D4672 +:1013800000262F46A06E10B90020BDE8F08101E0D4 +:10139000701C86B217F8011B0029F9D13146284686 +:1013A000A26E904780B2F0E7F0B51E49896B0968DC +:1013B0004968C1F5807188B21B490988884203DBFE +:1013C00019490988411A04E017490988C1F5807153 +:1013D00001448BB2002120E0134E36887218D617D4 +:1013E00002EB16663612A2EB0626104FBD5D104EBC +:1013F0003688721CD61702EB5666F611A2EBC6169B +:10140000B4B20C4A1288944205D00B4A084E368872 +:101410009555074A14804A1C91B29942DCDB024977 +:101420000880F0BD6406002038020020CC26012090 +:101430003402002036020020CC2701200FB42DE911 +:10144000F04105460E9F022D01DA012100E0002146 +:1014500008464FF48771EFF79DFB34263146002094 +:10146000F9F7EEFC044600BF201D07A91C2203E08B +:1014700011F8013B00F8013B131EA2F10106B2B2C4 +:10148000F6D100BF278084F830500A49E1625DB18F +:10149000012D04D1084860620849A16204E040F2CD +:1014A0001F110020EFF776FB2046BDE8F0015DF844 +:1014B00014FB000009930008719E0008D99E0008E3 +:1014C0007CB504460CB1012100E00021084644210E +:1014D000EFF760FB206970B12169D1E90401CDE922 +:1014E00000012569D5E902633246D5E90001B0471C +:1014F000204600F01CF87CBD7CB504460CB10121EF +:1015000000E0002108465321EFF744FB206968B151 +:101510002169D1E90401CDE900012569EE6833466E +:1015200095E80700B047204600F001F87CBD70B593 +:10153000044600250CB1012100E0002108460D21E0 +:10154000EFF728FB2588002D06DD00E000BF281EF0 +:10155000A5F101018DB2F9D170BD2DE9F34182B041 +:101560000446FF270CB1012100E000210846A92113 +:10157000EFF710FB94F8310001287ED100269AE0A5 +:1015800025460DB1012100E0002108468C21EFF72E +:1015900001FBE86860B1E968D1E90401CDE9000127 +:1015A000D5F80CC0DCF80C8043469CE80700C04727 +:1015B00000BF2046FFF7BBFF9DF80C0000F0800045 +:1015C000C8B125460DB1012100E000210846622185 +:1015D000EFF7E0FA686860B16968D1E90401CDE924 +:1015E0000001D5F804C0DCE902834246DCE90001D1 +:1015F000C04700BF19E025460DB1012100E00021E0 +:1016000008467021EFF7C6FA686860B16968D1E9E9 +:101610000401CDE90001D5F804C0DCF80C80434694 +:101620009CE80700C04700BF00BF2046FFF77FFFD0 +:1016300025460DB1012100E0002108467E21EFF78B +:10164000A9FAE86860B1E968D1E90401CDE90001CF +:10165000D5F80CC0DCE902834246DCE90001C04752 +:1016600000BF2046FFF763FF9DF80C004006000E08 +:1016700003907806070EA06800E023E00068C0B180 +:1016800025460DB1012100E0002108469A21EFF71F +:1016900081FAA968D1E90401CDE90001D5F808C0B3 +:1016A000DCF814809CE80F00C047012801D1781CA9 +:1016B000C7B2701CC6B2082EFFF662AF384604B03F +:1016C000BDE8F081002001904FF4FA600090012302 +:1016D00001AA03A9206AF2F7C1F908B1FF20EEE7D9 +:1016E0009DF80400EBE700000FB4F8B507A80090E0 +:1016F0004FF400611348009B069AF7F771FC05460A +:10170000002000900326104890F89C02032812D174 +:101710000D48D0F8BC72EFF7B1FE044605E0EFF7D4 +:10172000ADFE001BB04200D903E0D7F81402002838 +:10173000F5D100BF00BFA9B20248EFF70FFAF8BC1D +:101740005DF814FB0C1501203008012070B505462A +:101750000C46214601A0FFF7C7FF70BD6C656E20E7 +:101760003D2025640D0A00001CB5012000F0FEFBA1 +:101770001449086014481549886615484866154894 +:10178000C866154808674FF4007214490F48FEF701 +:101790004FFF4FF4807212491248F2F715FE1148BC +:1017A0000068C06840F010000E490968C860002059 +:1017B0000121064B8A02CDE900100BA10D4801F072 +:1017C0005DF81CBD3002002081180108582401205A +:1017D00011180108F917010865180108CC24012027 +:1017E000CC260120640600207368656C6C5F746110 +:1017F000736B0000C910010810B504464FF0FF31AB +:101800000248006800F018FF002010BD30020020E0 +:1018100030B502460B46002119E00F4800880F4CF6 +:101820002488A04200D114E00D480C4C2488055DAA +:1018300008464C1CA1B21554084C2488601CC417DF +:1018400000EB5464E411A0EBC414044D2C809942C5 +:10185000E3DB00BF08B230BD3402002036020020B6 +:10186000CC27012010B5044600231A461946034828 +:10187000006800F075FC002010BD00003002002060 +:1018800070B505460C4640F2FF1322462946024831 +:10189000F2F7BDFD20B270BD6406002001460A6962 +:1018A000D1E901309860D1E901035860506888425D +:1018B00001D188685060002008611068401E1060E7 +:1018C00010687047034B0360034B0B608023136069 +:1018D0007047000054020020A802002000F1080117 +:1018E00041604FF0FF31816000F10801C16001618A +:1018F00000210160704700210161704710B5024668 +:101900000B685C1C0CB9106907E002F1080000E0EC +:101910004068446824689C42FAD944684C604C682A +:10192000A160886041600A611468641C146010BD85 +:1019300042684A6093688B6093685960916008615F +:1019400003685B1C0360704700BF502080F3118860 +:10195000BFF34F8FBFF36F8F00BF0E480068401C6E +:101960000C49086008460068012812D10A4800683E +:10197000C0B208B9012000E0002050B900BF5020DB +:1019800080F31188BFF34F8FBFF36F8F00BF00BF8D +:10199000FEE770477000002004ED00E00D4800688D +:1019A00050B900BF502080F31188BFF34F8FBFF3B1 +:1019B0006F8F00BF00BFFEE706480068401E054964 +:1019C00008600846006820B9002080F3118800BF35 +:1019D00000BF70477000002070B506463546002EE7 +:1019E00044D0083D2C46224960680968084008B187 +:1019F000012000E0002050B900BF502080F3118882 +:101A0000BFF34F8FBFF36F8F00BF00BFFEE72068AB +:101A100008B9012000E0002050B900BF502080F339 +:101A20001188BFF34F8FBFF36F8F00BF00BFFEE77A +:101A30000F49606809680840C0B12068B0B90C4916 +:101A4000606809688843606000F08EF90949606841 +:101A500009680844074908602046F9F72DFE064842 +:101A60000068401C0449086001F068F970BD00007E +:101A70006C0000205C0000206800002000204FF077 +:101A8000E02108618861064800684FF47A71B0FB74 +:101A9000F1F0401E4FF0E0214861072008617047D7 +:101AA0001000002070B5EEF7D7FB0446102C16D3BB +:101AB00004F1E02090F8F05315480078854201DBEE +:101AC000012000E0002050B900BF502080F31188B1 +:101AD000BFF34F8FBFF36F8F00BF00BFFEE70D480E +:101AE000006800F4E0600C490968884201D80120D0 +:101AF00000E0002050B900BF502080F31188BFF3F0 +:101B00004F8FBFF36F8F00BF00BFFEE770BD0000B7 +:101B1000740000200CED00E07800002070B5044651 +:101B20000025D4B11248006808B9012000E0002067 +:101B300050B900BF502080F31188BFF34F8FBFF31F +:101B40006F8F00BF00BFFEE700F00EF900212046B6 +:101B5000F9F760FB01F0F2F805463DB94FF080500F +:101B600004490860BFF34F8FBFF36F8F70BD000053 +:101B70004C00002004ED00E00349096801600349BE +:101B800009684160704700003C00002028000020E8 +:101B900001200149086070473800002070B50446F4 +:101BA0000D4654B900BF502080F31188BFF34F8F0A +:101BB000BFF36F8F00BF00BFFEE705480168183113 +:101BC0002046FFF79BFE01212846F9F723FB70BD55 +:101BD000140000202DE9F04706460F4634464FF02A +:101BE0000109002E60D0A06C50B900BF502080F3D6 +:101BF0001188BFF34F8FBFF36F8F00BF00BFFEE7A9 +:101C0000606CB84201D23D4600E0656CE06AA842D3 +:101C10004AD0A06C012847D124480068844201D0F2 +:101C2000012000E0002050B900BF502080F311884F +:101C3000BFF34F8FBFF36F8F00BF00BFFEE7D4F835 +:101C40002C80E562A06900F0004010B9C5F10700E2 +:101C5000A06108EB8801164A02EB810160698842A5 +:101C600001D1012000E00020F0B1201DFFF716FE99 +:101C700040B994F82C10012088400E49096881432E +:101C80000C48016094F82C1001208840094909682B +:101C9000084308490860E16A01EB8101044A02EB4C +:101CA0008100211DFFF744FEBDE8F08714000020ED +:101CB000B00700202C00002010B586B00020059051 +:101CC000049003AA04A905A8FFF7FCFD0022DDE9A2 +:101CD00004101346CDE9002102901CA11D48039A6F +:101CE00000F0FEFD1C4908600846006808B10124A8 +:101CF00000E00024012C15D100BF502080F3118892 +:101D0000BFF34F8FBFF36F8F00BF4FF0FF3013490A +:101D1000086001201249086000201249086000F0A4 +:101D200071F810E0601C08B1012000E0002050B9FB +:101D300000BF502080F31188BFF34F8FBFF36F8F28 +:101D400000BF00BFFEE706B010BD000049444C458F +:101D50000000000031B500084800002044000020C9 +:101D6000300000202800002002480068401C014983 +:101D7000086070474C0000201D48006818B1012021 +:101D80001C49086032E000201A4908601A480068BF +:101D9000B0FA80F0C0F11F0101EB8100174A52F840 +:101DA000200008B1012000E0002050B900BF502001 +:101DB00080F31188BFF34F8FBFF36F8F00BF00BF59 +:101DC000FEE701EB81020D4B03EB82004268526893 +:101DD000426000F108024368934202D142685268AF +:101DE00042604268D268064B1A6000BF704700002C +:101DF0004C000020380000202C000020B0070020FC +:101E0000140000201CB5524800685249884201D095 +:101E1000012000E0002050B900BF502080F311885D +:101E2000BFF34F8FBFF36F8F00BF00BFFEE748487F +:101E300000684849491E884201D0012000E0002086 +:101E400050B900BF502080F31188BFF34F8FBFF30C +:101E50006F8F00BF00BFFEE73F4908460078019042 +:101E6000FF200A4610700846007800909DF8000098 +:101E700000F0F0009DF80020904201D1012000E028 +:101E8000002050B900BF502080F31188BFF34F8F5E +:101E9000BFF36F8F00BF00BFFEE79DF8000000F0AA +:101EA00050002E4A107007202D4A106009E02C487F +:101EB0000068401E2A4A10609DF800004006000E8F +:101EC00000909DF8000000F080008028EFD02448AA +:101ED0000068C0F10700042801D1012000E00020C3 +:101EE00050B900BF502080F31188BFF34F8FBFF36C +:101EF0006F8F00BF00BFFEE7194800680002184A54 +:101F000010601046008800F4E0601060124A0198EA +:101F100010700F482030006840F470000C492031E8 +:101F200008600846006840F070400860FFF7A6FDB2 +:101F300000200C490860EEF757F90B48006840F0A4 +:101F4000404009490860EEF73BF900201CBD000045 +:101F500000ED00E071C20F4100E400E074000020D9 +:101F6000780000207000002034EF00E02DE9F041FF +:101F700004460126002722460021012000F007F830 +:101F800005462846F9F7E8FA2846BDE8F0812DE92C +:101F9000F84305460E4617460DB1012000E000202B +:101FA00050B900BF502080F31188BFF34F8FBFF3AB +:101FB0006F8F00BF00BFFEE705FB06F808F1480081 +:101FC000F9F7A0FD044664B1A14609F148090020D3 +:101FD00084F846003B464A46314628460094F9F7C5 +:101FE000CAFA2046BDE8F8832DE9F84380460E463C +:101FF00017461D46DDF82090B8F1000F01D00120F2 +:1020000000E0002050B900BF502080F31188BFF3DA +:102010004F8FBFF36F8F00BF00BFFEE70DB10120F0 +:1020200000E0002050B900BF502080F31188BFF3BA +:102030004F8FBFF36F8F00BF00BFFEE707B10EB138 +:10204000012000E0002050B900BF502080F311882B +:10205000BFF34F8FBFF36F8F00BF00BFFEE707B91D +:102060000EB9012000E0002050B900BF502080F3DD +:102070001188BFF34F8FBFF36F8F00BF00BFFEE724 +:10208000482000900098482801D1012000E000205D +:1020900050B900BF502080F31188BFF34F8FBFF3BA +:1020A0006F8F00BF00BFFEE700BF2C464CB1012080 +:1020B00084F846004B463A46314640460094F9F7CC +:1020C0005AFA2046BDE8F88370B505460E462C4600 +:1020D00054B900BF502080F31188BFF34F8FBFF376 +:1020E0006F8F00BF00BFFEE7FFF72EFCD4E90F1291 +:1020F000206801FB0200A0600020A06320686060EF +:10210000E06B401E226C216800FB0211E160FF20A1 +:1021100084F8440084F845009EB9206908B901207C +:1021200000E00020A8B904F1100000F0BBFD80B170 +:102130004FF0805009490860BFF34F8FBFF36F8F96 +:1021400007E004F11000FFF7C9FB04F12400FFF7DA +:10215000C5FBFFF723FC012070BD000004ED00E08B +:102160002DE9FF4383B0064688461D464FF000091F +:10217000344654B900BF502080F31188BFF34F8F0D +:10218000BFF36F8F00BF00BFFEE7B8F1000F01D1B2 +:10219000206C08B9012000E0002050B900BF502099 +:1021A00080F31188BFF34F8FBFF36F8F00BF00BF65 +:1021B000FEE7022D02D1E06B012801D1012000E0F1 +:1021C000002050B900BF502080F31188BFF34F8F1B +:1021D000BFF36F8F00BF00BFFEE700F0DFFB08B961 +:1021E000059808B9012000E0002050B900BF502038 +:1021F00080F31188BFF34F8FBFF36F8F00BF00BF15 +:10220000FEE700BFFFF7A0FBA06BE16B884201D3A4 +:10221000022D28D12A4641462046F9F7DAF807462A +:10222000606A08B9012000E0002068B904F12400C8 +:1022300000F038FD88B14FF0805032490860BFF39C +:102240004F8FBFF36F8F08E03FB14FF080502D49A3 +:102250000860BFF34F8FBFF36F8FFFF79FFB012025 +:1022600007B0BDE8F083059818B9FFF797FB002089 +:10227000F6E7B9F1000F04D101A8FFF77DFC4FF09C +:102280000109FFF78BFBFFF76FFDFFF75DFB94F98B +:102290004400401C10B9002084F8440094F9450023 +:1022A000401C10B9002084F84500FFF777FB05A912 +:1022B00001A800F09DFAF0B92046F9F73EFAA0B166 +:1022C00004F110000599FFF769FC2046F9F77EFA42 +:1022D00000F034FD002895D14FF080500949086086 +:1022E000BFF34F8FBFF36F8F8CE72046F9F76EFA7D +:1022F00000F024FD86E72046F9F768FA00F01EFD9D +:102300000020ADE704ED00E02DE9F84F07468A46CE +:1023100090461E463C4654B900BF502080F31188B9 +:10232000BFF34F8FBFF36F8F00BF00BFFEE7BAF15F +:10233000000F01D1206C08B9012000E0002050B945 +:1023400000BF502080F31188BFF34F8FBFF36F8F12 +:1023500000BF00BFFEE7022E02D1E06B012801D1D1 +:10236000012000E0002050B900BF502080F3118808 +:10237000BFF34F8FBFF36F8F00BF00BFFEE7FFF7C4 +:1023800091FB00BF5021EFF3118081F31188BFF35F +:102390004F8FBFF36F8F00BF0546A06BE16B884284 +:1023A00001D3022E25D194F945B0A06B009032469E +:1023B00051462046F9F70DF80BF1010088B9606A23 +:1023C00008B9012000E0002050B904F1240000F019 +:1023D00069FC28B1B8F1000F02D00120C8F8000054 +:1023E00004E00BF1010040B284F845004FF0010910 +:1023F00001E04FF0000900BF85F3118800BF484697 +:10240000BDE8F88F2DE9F74183B005460E464FF041 +:1024100000082C4654B900BF502080F31188BFF348 +:102420004F8FBFF36F8F00BF00BFFEE70EB9206C68 +:1024300008B9012000E0002050B900BF502080F30F +:102440001188BFF34F8FBFF36F8F00BF00BFFEE750 +:1024500000F0A4FA08B9059808B9012000E00020AE +:1024600050B900BF502080F31188BFF34F8FBFF3E6 +:102470006F8F00BF00BFFEE700BFFFF765FAA76BD5 +:10248000F7B131462046F8F78FFF781EA063206928 +:1024900008B9012000E0002060B904F1100000F04C +:1024A00001FC38B14FF080502F490860BFF34F8FC7 +:1024B000BFF36F8FFFF772FA012006B0BDE8F0811D +:1024C000059818B9FFF76AFA0020F6E7B8F1000F8F +:1024D00004D101A8FFF750FB4FF00108FFF75EFAA7 +:1024E000FFF742FCFFF730FA94F94400401C10B9A2 +:1024F000002084F8440094F94500401C10B90020E5 +:1025000084F84500FFF74AFA05A901A800F070F920 +:10251000F0B92046F9F704F9A0B104F124000599B7 +:10252000FFF73CFB2046F9F751F900F007FC0028C3 +:10253000A3D14FF080500C490860BFF34F8FBFF319 +:102540006F8F9AE72046F9F741F900F0F7FB94E71F +:102550002046F9F73BF900F0F1FB2046F9F7E0F8E7 +:1025600000288AD00020A8E704ED00E02DE9F05F04 +:10257000064689461746344654B900BF502080F3BA +:102580001188BFF34F8FBFF36F8F00BF00BFFEE70F +:10259000B9F1000F01D1206C08B9012000E0002042 +:1025A00050B900BF502080F31188BFF34F8FBFF3A5 +:1025B0006F8F00BF00BFFEE7FFF774FA00BF502126 +:1025C000EFF3118081F31188BFF34F8FBFF36F8F4B +:1025D00000BF0546D4F838A0BAF1000F22D094F914 +:1025E00044B049462046F8F7DFFEAAF10100A06397 +:1025F0000BF1010070B9206908B9012000E000204A +:1026000068B904F1100000F04DFB40B13FB101206A +:10261000386004E00BF1010040B284F844004FF050 +:10262000010801E04FF0000800BF85F3118800BFEA +:102630004046BDE8F09F00002DE9F34182B0054619 +:102640004FF000082C46002654B900BF502080F3FC +:102650001188BFF34F8FBFF36F8F00BF00BFFEE73E +:10266000206C08B9012000E0002050B900BF5020C4 +:1026700080F31188BFF34F8FBFF36F8F00BF00BF90 +:10268000FEE700F08BF908B9039808B9012000E0D3 +:10269000002050B900BF502080F31188BFF34F8F46 +:1026A000BFF36F8F00BF00BFFEE700BFFFF74CF91D +:1026B000A76BFFB1781EA063206810B9F9F7C8FABC +:1026C000A060206908B9012000E0002060B904F191 +:1026D000100000F0E7FA38B14FF08050434908602D +:1026E000BFF34F8FBFF36F8FFFF758F9012004B08E +:1026F000BDE8F081039898B90EB9012000E00020F0 +:1027000050B900BF502080F31188BFF34F8FBFF343 +:102710006F8F00BF00BFFEE7FFF740F90020E6E73C +:10272000B8F1000F04D16846FFF726FA4FF0010810 +:10273000FFF734F9FFF718FBFFF706F994F94400A7 +:10274000401C10B9002084F8440094F94500401C56 +:1027500010B9002084F84500FFF720F903A9684666 +:1027600000F046F840BB2046F8F7DAFFF0B12068E9 +:1027700038B9FFF7E9F8A06800F038FA0646FFF725 +:102780000DF904F124000399FFF708FA2046F9F740 +:102790001DF800F0D3FA002888D14FF0805013497B +:1027A0000860BFF34F8FBFF36F8F7FE72046F9F7C5 +:1027B0000DF800F0C3FA79E72046F9F707F800F0C2 +:1027C000BDFA2046F8F7ACFF0028EED05EB1FFF767 +:1027D000BBF82046F8F764FE07463946A068FFF7C5 +:1027E000F9F9FFF7DBF8002081E7000004ED00E0D5 +:1027F00070B505460C4655B900BF502080F31188CE +:10280000BFF34F8FBFF36F8F00BF00BFFEE754B918 +:1028100000BF502080F31188BFF34F8FBFF36F8F3D +:1028200000BF00BFFEE7FFF78FF812480268686834 +:10283000131A2068401C08B9002617E00E492868C2 +:102840000968884204D06868904201D801260DE0EA +:102850002068984207D92068C01A20602846FFF7F0 +:102860008BF9002602E0002020600126FFF796F891 +:10287000304670BD280000203C0000202DE9FF4FAD +:1028800085B0804689461746DDE912ABB800F9F7F6 +:1028900039F9064656B15420F9F734F904460CB11B +:1028A000266304E03046FFF797F800E000248CB17F +:1028B000002084F85100CDE900ABCDE902403A4652 +:1028C00049464046089BF8F769FE2046F8F7EEFCBB +:1028D000012501E04FF0FF35284609B0BDE8F08F33 +:1028E0002DE9F04F85B00746884691469A46DDE9C6 +:1028F0000EB6109C0EB1012000E0002050B900BFC0 +:10290000502080F31188BFF34F8FBFF36F8F00BF4C +:1029100000BFFEE70CB1012000E0002050B900BF6D +:10292000502080F31188BFF34F8FBFF36F8F00BF2C +:1029300000BFFEE7542003900398542801D10120E2 +:1029400000E0002050B900BF502080F31188BFF391 +:102950004F8FBFF36F8F00BF00BFFEE700BFB4B162 +:10296000AEB125462C462E63022085F8510000208A +:1029700004A953464A46CDE900B1CDE9025041468B +:102980003846F8F70BFE2846F8F790FC01E00020E7 +:102990000490049805B0BDE8F08F0000054909686F +:1029A00009B9012005E00449096809B9022000E0DD +:1029B00000207047300000204C00002001490868CA +:1029C000704700002800002070B5FFF76BF8002565 +:1029D00001480468204670BD280000202DE9F04120 +:1029E0004FF000084448006800287CD14348006844 +:1029F000451C4248056015BB41480068006808B99D +:102A0000012000E0002050B900BF502080F3118861 +:102A1000BFF34F8FBFF36F8F00BF00BFFEE7384893 +:102A20000768384800683649086036480760364805 +:102A30000068401C34490860F8F78EFE00BF334838 +:102A4000006885423CD300BF2D480068006808B983 +:102A5000012000E0002020B14FF0FF302B4908603A +:102A60002DE027480068C068C4686668B54202D295 +:102A70002648066023E0201DFEF710FFA06A18B16B +:102A800004F11800FEF70AFF94F82C10012088408A +:102A90001F49096808431E490860E16A01EB81018A +:102AA0001C4A02EB8100211DFEF742FF1A49E06A31 +:102AB0000968C96A8842C7D34FF00108C4E700BF5C +:102AC00015480068C06A00EB8000124951F82000E8 +:102AD000012801D94FF001081048006808B14FF0F3 +:102AE000010805E0FFE70E480068401C0C4908603B +:102AF0004046BDE8F08100004C0000202800002086 +:102B0000180000201C0000203C0000204400002091 +:102B10002C000020B0070020140000203800002006 +:102B20003400002070B505462C460026002D55D0F7 +:102B30002B480068844201D1012000E0002050B9F8 +:102B400000BF502080F31188BFF34F8FBFF36F8F0A +:102B500000BF00BFFEE7A06C50B900BF502080F35B +:102B60001188BFF34F8FBFF36F8F00BF00BFFEE729 +:102B7000A06C401EA064616CE06A88422ED0A06CFC +:102B800060BB201DFEF78AFE78B9E06A00EB80008A +:102B9000144951F8200040B994F82C1001208840C5 +:102BA00011490968814310480160606CE062E06A85 +:102BB000C0F10700A06194F82C10012088400A4958 +:102BC0000968084308490860E16A01EB8101054A88 +:102BD00002EB8100211DFEF7ABFE0126304670BDE1 +:102BE00014000020B00700202C00002070B505461E +:102BF0002C460026002D4DD02749E06A0968C96A95 +:102C0000884240D2A06900F0004028B922480068FC +:102C1000C06AC0F10700A061E16A01EB81011F4AAF +:102C200002EB81016069884201D1012000E00020AF +:102C300018B3201DFEF732FE40B994F82C10012085 +:102C400088401749096881431548016012480068A7 +:102C5000C06AE06294F82C1001208840104909688D +:102C600008430F490860E16A01EB81010B4A02EB5E +:102C70008100211DFEF75CFE03E007480068C06A82 +:102C8000E062012606E00449606C0968C96A88426E +:102C900000D20126304670BD14000020B00700208D +:102CA0002C00002070B50646F068C46854B900BF17 +:102CB000502080F31188BFF34F8FBFF36F8F00BF99 +:102CC00000BFFEE704F11800FEF7E8FD15480068B4 +:102CD000A8B9201DFEF7E2FD94F82C1001208840D1 +:102CE00011490968084310490860E16A01EB810154 +:102CF0000E4A02EB8100211DFEF71AFE04E004F1EA +:102D000018010B48FEF714FE0A49E06A0968C96A0F +:102D1000884204D9012501200749086000E0002508 +:102D2000284670BD4C0000202C000020B007002079 +:102D300064080020140000203800002070B5002432 +:102D400000263648006850B900BF502080F3118833 +:102D5000BFF34F8FBFF36F8F00BF00BFFEE7FEF7DB +:102D6000F3FD2E480068401E2C49086008460068A4 +:102D700000284FD12A48006800284BD024E0294879 +:102D8000C068C46804F11800FEF788FD201DFEF736 +:102D900085FD94F82C1001208840234909680843D8 +:102DA00021490860E16A01EB8101204A02EB8100C0 +:102DB000211DFEF7BDFD1E49E06A0968C96A884207 +:102DC00002D301201B4908601648006808B9012099 +:102DD00000E000200028D2D00CB1F8F7BDFC164866 +:102DE000056865B100BFFFF7F9FD10B10120114979 +:102DF00008606D1E002DF6D100200F4908600D48B7 +:102E0000006838B1012630070C490860BFF34F8FC6 +:102E1000BFF36F8FFEF7C2FD304670BD4C0000203F +:102E200024000020640800202C000020B0070020AF +:102E300014000020380000203400002004ED00E0E1 +:102E4000D85D0108BB5C0008000000000000000025 +:102E500080000000000000000000000000061016C6 +:102E6000000610160000000000000000010203042C +:102E700006070809000000000102030473676C5F85 +:102E80006F626A5F7365745F6469727479007367F7 +:102E90006C5F6F626A5F7365745F73697A65000067 +:102EA000FFFF000073676C5F6F626A5F7365745F3A +:102EB00064697274790073676C5F6F626A5F7365CF +:102EC000745F73697A6500005F050000E0FF000031 +:102ED00008FA000010FC0000F08700001F840000CA +:102EE000F0FF0000FF87000014A500001FFC000099 +:102EF000FFFF0000FFFF0000FF07000000000000D0 +:102F0000000000000200F000F000000000000000DF +:102F100000000000000000000000000000000300AE +:102F200000000000000000000000000000000000A1 +:102F300000000000B4440020000000006009000010 +:102F4000F000F000F5DC00085F6C697374006C69D8 +:102F5000737420616C6C20636F6D6D616E64000032 +:102F60000010000000080000080000000800000039 +:102F700000800000004000007D590008D95A000878 +:102F8000555A0008E55A0008E95900080A000000EF +:102F90000200000000000000000000006C65747476 +:102FA0006572000064656661756C74207573657286 +:102FB00000736574566172007365742076617200E7 +:102FC000757000646F776E007269676874006C6575 +:102FD000667400746162006261636B737061636543 +:102FE000006261636B73706163650064656C657436 +:102FF0006500656E74657200656E74657200686563 +:103000006C700073686F7720636F6D6D616E642004 +:10301000696E666F0D0A68656C70205B636D645D38 +:10302000007573657273006C69737420616C6C2039 +:103030007573657200636D6473006C6973742061ED +:103040006C6C20636D640076617273006C697374DC +:1030500020616C6C20766172006B657973006C691D +:10306000737420616C6C206B657900636C656172B0 +:1030700000636C65617220636F6E736F6C65000036 +:1030800000112233445566778899AABBCCDDEEFF48 +:103090000055AAFF73676C5F6F626A5F6E6F64654D +:1030A0005F696E69740073676C5F6F626A5F7365F6 +:1030B000745F64657374726F7965640073676C5FC5 +:1030C0006F626A5F69735F64657374726F79656458 +:1030D0000073676C5F6F626A5F7365745F646972C7 +:1030E00074790073676C5F6F626A5F636C656172AD +:1030F0005F64697274790073676C5F6F626A5F699D +:10310000735F64697274790073676C5F6F626A5F82 +:1031100069735F6E656564696E69740073676C5F7F +:103120006F626A5F636C6561725F6E656564696E2C +:1031300069740073676C5F6F626A5F69735F686967 +:103140006464656E0073676C5F6F626A5F67657465 +:103150005F66696C6C5F726563740073676C5F6156 +:103160007265615F696E69740073676C5F61726537 +:10317000615F69735F6F7665726C61700073676C15 +:103180005F617265615F73656C666D65726765002E +:1031900073676C5F666F6E745F6765745F6865699F +:1031A0006768740073676C5F66626465765F7265FA +:1031B0006769737465720002010102020304010170 +:1031C0000202030473676C5F7069786D616C5F67FE +:1031D00065745F62797465735F7065725F7069783A +:1031E000656C0073676C5F6F626A5F6164645F63E4 +:1031F00068696C640073676C5F6F626A5F72656DAB +:103200006F76650073676C5F6F626A5F6D6F76657E +:103210005F6368696C645F706F730073676C5F6F86 +:10322000626A5F7365745F6162735F706F7300736E +:10323000676C5F6F626A5F73697A655F7A6F6F6DE3 +:103240000073676C5F6F626A5F6D6F76655F757044 +:103250000073676C5F6F626A5F6D6F76655F646F46 +:10326000776E0073676C5F6F626A5F6D6F76655F24 +:10327000746F700073676C5F6F626A5F6D6F766505 +:103280005F626F74746F6D00FFFF73676C5F7363D1 +:103290007265656E5F6C6F61640073676C5F61720D +:1032A00065615F636C69700073676C5F6172656113 +:1032B0005F73656C66636C69700073676C5F6469EB +:1032C0007274795F617265615F70757368007367AE +:1032D0006C5F6F626A5F696E69740073676C5F6FC1 +:1032E000626A5F667265650073676C5F6F626A5FD2 +:1032F000636C6561725F616C6C5F646972747900A4 +:1033000073676C5F666F6E745F6765745F7374720A +:10331000696E675F77696474680073676C5F67657F +:10332000745F616C69676E5F706F730073676C5F69 +:103330006765745F746578745F706F730073676C32 +:103340005F6765745F69636F6E5F706F730073674B +:103350006C5F6F626A5F7365745F706F735F616CDF +:1033600069676E0073676C5F6F626A5F7365745F35 +:10337000706F735F616C69676E5F7265660064721F +:1033800061775F6F626A5F736C6963650073676C16 +:103390005F64697274795F617265615F63616C63B8 +:1033A000756C617465000000000000000000000002 +:1033B00000000000120000000000000000000000FB +:1033C000000000000E00000073676C5F647261779C +:1033D0005F7461736B0073676C5F616E696D5F72C0 +:1033E000656D6F76650073676C5F616E696D5F73A5 +:1033F000746172740073676C5F616E696D5F737482 +:103400006F700073676C5F616E696D5F64656C659A +:1034100074650073676C5F616E696D5F7461736B77 +:103420000073676C5F6F626A5F6861735F6368698E +:103430006C640073676C5F6F626A5F6861735F736F +:1034400069626C696E670073676C5F6F626A5F695F +:10345000735F68696464656E0073676C5F6F626A4E +:103460005F69735F636C69636B61626C6500636C59 +:1034700069636B5F6465746563745F6F626A6563DB +:10348000740073676C5F6576656E745F7461736BEF +:10349000000000003C027804B306EE08280B610D22 +:1034A000990FD01106143A166C189D1ACB1CF71EF2 +:1034B000212148236C258E27AC29C72BDF2DF32F24 +:1034C0000332103418361C381C3A173C0E3EFF3FAE +:1034D000EC41D443B64593476A493C4B084DCD4E29 +:1034E0008D504652F953A5554B57EA58825A135CF2 +:1034F0009C5D1F5F9A600D627963DD6439668D673C +:10350000D9681D6A596B8C6CB76DD96EF36F0471F5 +:103510000C720B730174EE74D275AD767F774778B9 +:103520000679BB79677A0A7BA27B327CB77C337DD4 +:10353000A57D0D7E6C7EC07E0B7F4B7F827FAF7F33 +:10354000D27FEB7FFA7FFF7F00006ABB003C73A550 +:10355000D4002951769BBDDF001F3E5B7895B0CB30 +:10356000E60019324A627A91A8BED4EA00152A3ED2 +:1035700053677B8EA2B5C8DBED0012243647596A2B +:103580007B8C9DAEBECFDFEF000F1F2F3F4E5D6DDA +:103590007C8B9AA9B7C6D4E3F1000E1C2A38465397 +:1035A000616F7C8A97A4B2BFCCD9E6F3000C1926D0 +:1035B000323F4B5864707C8995A1ADB9C5D1DCE828 +:1035C000F4000B17222E3944505B66727D88939E5F +:1035D000A9B4BFCAD5DFEAF5000A151F2A343F494E +:1035E000545E68737D87919CA6B0BAC4CED8E2ECD5 +:1035F000F60009131D27303A444D57616A747D87E0 +:103600009099A3ACB6BFC8D1DBE4EDF60009121B5C +:10361000242D363F48515A636C747D868F98A0A93B +:10362000B2BBC3CCD5DDE6EEF700081119212A3272 +:103630003B434C545C656D757D868E969EA7AFB7F7 +:10364000BFC7CFD7DFE7EFF700070F171F272F37C9 +:103650003F474F575E666E767E858D959CA4ACB4D1 +:10366000BBC3CAD2DAE1E9F0F800070F161E252C19 +:10367000343B434A525960686F767E858C949BA296 +:10368000A9B1B8BFC6CDD5DCE3EAF1F800070E1545 +:103690001C232A31383F464D545B626970777E8522 +:1036A0008C9299A0A7AEB5BCC2C9D0D7DEE4EBF22C +:1036B000F900060D141A21282E353C424950565D5A +:1036C000646A71777E848B92989FA5ACB2B9BFC6AD +:1036D000CCD3D9DFE6ECF3F900060C13191F262C26 +:1036E00032393F454C52585F656B71787E848A91C0 +:1036F000979DA3A9B0B6BCC2C8CFD5DBE1E7EDF377 +:10370000F900060C12181E242A30363C42484E544A +:103710005A60666C72787E848A90969CA2A8ADB33B +:10372000B9BFC5CBD1D7DCE2E8EEF4FA00050B1146 +:10373000171D22282E34393F454B50565C62676D69 +:1037400073787E84898F959AA0A6ABB1B7BCC2C8A6 +:10375000CDD3D8DEE4E9EFF4FA00050B10161B21F7 +:10376000262C31373C42474D52585D63686E737961 +:103770007E84898E94999FA4AAAFB4BABFC5CACFDC +:10378000D5DADFE5EAEFF5FA00050A0F151A1F256D +:103790002A2F353A3F444A4F545A5F64696E747910 +:1037A0007E83898E93989DA3A8ADB2B7BDC2C7CCC6 +:1037B000D1D6DCE1E6EBF0F5FA00050A0F14191E8C +:1037C00023282D32383D42474C51565B60656A6F65 +:1037D00074797E83888D92979CA1A6ABB0B5BABF51 +:1037E000C4C9CED3D8DDE2E7ECF1F6FB0004090E44 +:1037F00013181D22272C31353A3F44494E53585C4B +:1038000061666B7075797E83888D92969BA0A5AA60 +:10381000AEB3B8BDC2C6CBD0D5D9DEE3E8EDF1F684 +:10382000FB0004090E12171C21252A2F33383D42B4 +:10383000464B5054595E62676C70757A7E83888CF3 +:1038400091969A9FA3A8ADB1B6BBBFC4C8CDD2D63E +:10385000DBDFE4E9EDF2F6FB0004090D12161B1F95 +:1038600024292D32363B3F44484D51565A5F6368F8 +:103870006C71757A7E83878C9095999EA2A7ABB068 +:10388000B4B9BDC1C6CACFD3D8DCE1E5E9EEF2F7E1 +:10389000FB0004080D11161A1E23272C3034393D65 +:1038A00041464A4F53575C6064696D71767A7E83F6 +:1038B000878B9094989DA1A5AAAEB2B7BBBFC4C890 +:1038C000CCD0D5D9DDE2E6EAEEF3F7FB0004080C34 +:1038D0001115191D22262A2E33373B3F43484C50E1 +:1038E00054595D6165696E72767A7E83878B8F939A +:1038F000989CA0A4A8ACB1B5B9BDC1C5CACED2D65A +:10390000DADEE3E7EBEFF3F7FB0004080C10141822 +:103910001C2025292D3135393D4145494E52565AF5 +:103920005E62666A6E72767A7E83878B8F93979BD0 +:103930009FA3A7ABAFB3B7BBBFC3C7CBCFD3D7DBB7 +:10394000DFE3E7EBEFF3F7FB000001010202020304 +:103950000303030404040404050505050505060620 +:103960000606060606070707070000000000080213 +:1039700000020208020608080608080E000C060EDF +:103980000900110209020B0E0B0C110E0F06110C8F +:103990000D060F081200140E140C1A0E73676C5FDC +:1039A0006F626A5F7365745F6469727479007367CC +:1039B0006C5F6F626A5F7365745F73697A650073C9 +:1039C000676C5F6F626A5F6765745F77696474686C +:1039D0000073676C5F6F626A5F6765745F686569D3 +:1039E0006768740073676C5F6F626A5F7365745FAA +:1039F000626F726465725F77696474680073676C84 +:103A00005F616E696D5F7365745F6461746100739B +:103A1000676C5F616E696D5F7365745F7061746818 +:103A20000073676C5F616E696D5F7365745F73745B +:103A30006172745F76616C75650073676C5F616E4F +:103A4000696D5F7365745F656E645F76616C7565E3 +:103A50000073676C5F616E696D5F7365745F61634E +:103A6000745F6475726174696F6E0073676C5F6117 +:103A70006E696D5F69735F66696E6973686564001E +:103A800000F800001F000000E00700001F00000019 +:103A90001F0000001F0073676C5F7069786D6170B4 +:103AA0005F6765745F6275660000000000008EC08D +:103AB00000000000AFE000000000AFE000000000E8 +:103AC0008EC0000000005EC0000000003EA00000AC +:103AD00000003C80000000003C80000000000C80E2 +:103AE000000000000A50000000000A500000000022 +:103AF0000000000000000000000000008EC0000078 +:103B00000000CFE5000000008EC000000003EE586A +:103B1000EC00000AFE5EFE00003EE88EE30000AE10 +:103B200080EE300003EA08C5000008A00A5000003B +:103B3000000CA000AC00000A8000AC00000C80006B +:103B4000CA00033C8333CA308EFFFFFFFFE85AAC44 +:103B5000CAAAECA5005A3000A500005A3003A500FF +:103B6000008C0005A300008C0005A3008CEECCCED9 +:103B7000FCC88EFFFFFFFFE800CA000AC00000CAB1 +:103B8000000AC00000A8000AC00000C8000CA00085 +:103B900000000880000000000AC000000003CFFE03 +:103BA000A000005ECAC8EC0000EE0AC3EE3003ECD1 +:103BB0000AC8EC0003EE3AC0000000AFEAC0000003 +:103BC000000CFFC000000000AEFC000000000AFF77 +:103BD000C00000000ACEFA0000000AC3EE3005EE75 +:103BE0000AC0AE500AFE3AC0AE5008EA0AC0CE3053 +:103BF00000EE5AC8C800000AEFFC500000000AC0DE +:103C0000000000000AC000000000035000000AEE9F +:103C10005000AA008C5AE3038300CE05C80AA00016 +:103C2000EC03EA0A5000EC03EA8A0000EC03EAC85D +:103C30000000CE05C8A300008C5AEAAAEE800AEE66 +:103C40008A6C8AE300008AAE05C80000A5EC03EA8E +:103C50000005A0EC03EA000A80EC03EA003830CE4D +:103C600005C800AA005A5AE303A5000AEE80003CEA +:103C7000FEA0000000CE38C8000003EA05EA0000FC +:103C800005C805EA000003EA08C5000003EC0CC003 +:103C9000000000CEAA00000000CFA05EFFC00CAE66 +:103CA000E003EA008C3CE803A500CE05EE05A00089 +:103CB000EE00AFAAA000EE303EEA5000CE5005EE76 +:103CC00030333EE508CEE3AA03CFEC35EFC308EE70 +:103CD000500000000AFFA000000000AEA00000009D +:103CE000005C8000000000CC000000000AA0000082 +:103CF0000000000000000AA0000000008C3000005E +:103D00000005A5000000000EC000000000AE30005D +:103D1000000003EC0000000008C8000000000CE3F5 +:103D2000000000000EE0000000003EE00000000087 +:103D30003EC0000000003EE0000000000EE0000079 +:103D400000000CE30000000008C80000000003ECC5 +:103D50000000000000AE30000000003EA0000000A7 +:103D60000005A500000000008C30000000000AA043 +:103D70000A800000000003C800000000008C500012 +:103D80000000000CE00000000005C800000000007A +:103D9000CE00000000008C80000000005EA000004B +:103DA00000003EE0000000000EE0000000000EE019 +:103DB000000000000EE0000000003EE000000000F7 +:103DC0005EA0000000008C8000000000CE0000001B +:103DD0000005EA000000000CE0000000008C50002C +:103DE000000003C8000000000A800000000000007E +:103DF0003EE3000000003EE3000000003EE0000063 +:103E00003EE50EC08EE00AEE5CAAFEA00005A8AA60 +:103E100050000005AAAA50000AEEAAAAFEA05EE57C +:103E20000EC08EE300003EE0000000005EE30000F4 +:103E300000005EE0000000000AC0000000000AC0B0 +:103E4000000000000AC0000000000AC000000000DE +:103E50000AC000003EFFFFFFFFE500000AC00000AF +:103E600000000AC0000000000AC0000000000AC0F4 +:103E7000000000000AC0000008EE500000000AFF29 +:103E8000A000000000AFA0000000005C8000000067 +:103E900000CC000000000AA000000000AFFFFFFF00 +:103EA000FFE008EE300000000CFE8000000008EE8D +:103EB00030000000000000000383000000000AC082 +:103EC000000000003A5000000000AC0000000003B9 +:103ED000A50000000008C0000000000A500000001B +:103EE000008C0000000000A50000000008C00000D9 +:103EF00000000C80000000008C0000000000C800E2 +:103F000000000008C0000000000A80000000008CD3 +:103F10000000000000C80000000008A00000000031 +:103F20000C80000000005A00000000000005CFFCDB +:103F30003000005EE33EE50000EE5003EE0008ECCA +:103F40000000CE500CE80000AFA00EE500008EC0CF +:103F50003EE300005EE03EE300005EE03EE3000082 +:103F60005EE03EE300005EE00EE500008EC00CE87F +:103F70000000AFA008EC0000CE5000EE5005EC00B1 +:103F8000005EE33EE3000005CFFC30000000038349 +:103F90000000005ACFE3000000368EE3000000006E +:103FA0000EE3000000000EE3000000000EE300003E +:103FB00000000EE3000000000EE3000000000EE32E +:103FC000000000000EE3000000000EE3000000000F +:103FD0000EE3000000000EE3000000000EE300000E +:103FE00000005EE80000008EFFFFFC00000AEFFE0C +:103FF000A00000CC500AEE000AE50000CE800CE5DF +:1040000000008EA00CFC00008EA003630000AE80B8 +:1040100000000003EE000000000AE3000000008C36 +:104020003000000008C3000000008C3000000008D1 +:10403000C3000000008C300008A005A500000CA003 +:104040003EC66666CE803EFFFFFFFE50003AEFFCA4 +:10405000500000CC305EE50008C80005EE0008EC1A +:104060000000EE3000530000EE0000000005EA0002 +:104070000000005CA0000000AFFC30000000003C2D +:10408000E80000000000EE30000000008EA00053A9 +:1040900000008EC00CFC00008EA00CFA0000CE5078 +:1040A00003EC303CFA00003CEFFC50000000000E36 +:1040B000C000000000AFC000000005EFC00000001D +:1040C0000ECEC0000000CE5EC0000008C55EC0007D +:1040D000003C805EC00000CC005EC00008C0005EF6 +:1040E000C0003A50005EC0008EFFFFFFFFE50000F9 +:1040F000005EC0000000005EC0000000005EC00066 +:104100000000008EE3000000AFFFFFE000CFFFFFE4 +:10411000FE8000AA6666653000A80000000000C8A6 +:104120000000000000A50000000000A50000000045 +:1041300003A5CFFEA00003AA8008EC0000A80000A1 +:10414000CE50000000008EA0000000005EC008CA33 +:1041500000005EC00CFC00008EA00AE50000CE50FE +:1041600003EC303CFA00003AEFFE80000000AEFFA6 +:10417000C300000CE505EE0000CE3005EE3005EA88 +:10418000000033000AE8000000000EE50000000017 +:104190000EE3AEFFC3003EECC305EE303EFC000074 +:1041A0008EA03EE300003EE03EE300003EE00EE570 +:1041B00000003EE00AFA00003EC005EE30008C80B0 +:1041C00000AEE305EC000005CFFEA00005EFFFFF09 +:1041D000FFE008EC66668C800AC00000AC000A8034 +:1041E0000003A5000000000AA0000000003A5000F3 +:1041F000000000AC0000000003C8000000000AE35B +:10420000000000000EC0000000005EA000000000E2 +:10421000AE8000000000CE8000000000EFA0000093 +:104220000003EFA000000000CE800000003AEFFE87 +:10423000A00000EE5008EC000AE50000AE800CE0A3 +:1042400000005EA00CE300005C8008EE3000AE30A1 +:1042500000AEE805A5000008EFFE300000AC35CF49 +:10426000E30008C5000AEE300EC00000AFA03EA07B +:1042700000003EC03EA000003EC00EE300008C8067 +:1042800003EE5008EC00003AEFFE8000003AEFFC2D +:10429000500000EE503CE8000AE80000EE300EE36B +:1042A0000000AE803EE000008EC03EE000008EC008 +:1042B0003EE00000AFE00EE50003EFE008EE505CEA +:1042C0008EE0005CFFE8AFC000000000CFA000005F +:1042D0000000EE5000300005EE0005EE300CE80066 +:1042E00005EE33CFA000005EFFE500000000AEC089 +:1042F00000000000EFE300000000AEC0000000007E +:1043000000000000000000000000000000000000AD +:104310000000000000000000000000000000AEC02F +:1043200000000000EFE300000000AEC0000000004D +:104330008EE3000000008CC30000000000000000BD +:10434000000000000000000000000000000000006D +:10435000000000000000000000000000000000005D +:104360008CC3000000008EE3000000000CC00000C1 +:1043700000005A500000000000005A300000000504 +:10438000A5000000005A5000000005A50000000034 +:104390005A5000000005A5000000005A500000001F +:1043A00005A50000000005A500000000005A50000F +:1043B00000000005A500000000005A5000000000A9 +:1043C00005A500000000005A500000000005A500EF +:1043D000000000005A30AFFFFFFFFFE000000000C8 +:1043E0000000000000000000000000000000AFFF1F +:1043F000FFFFFFE00AC00000000000CC000000004A +:10440000000CC00000000000CC00000000000CC048 +:104410000000000000CC00000000000CC000000004 +:104420000000CC0000000000CC000000000CC00028 +:10443000000000CC000000000CC000000000CC0018 +:104440000000000CC000000000CC000000000AC00A +:10445000000000000008EFFEA30000CC3005EE30A5 +:104460000AC000008EC00EA000005EE00EEA000050 +:104470005EE00CFC0000AFA00000000ACA000000D3 +:1044800003EC500000000CA0000000000C800000B5 +:1044900000000C8000000000000000000000000090 +:1044A000000000008EC000000000CFE5000000000A +:1044B0008EC000000000AEFFC300003EE503AC501C +:1044C00000CC30000AC008C505EEEAC80CE03EC5C5 +:1044D000C8CA3EC0CE05A5AA3EA3EA08C3AC5EA8E2 +:1044E000C50AE0AA5EAAE30CE0CA5EACE33EC3A53F +:1044F0003EAAE3CFAAC00CE0CFCAEC3008C500004A +:1045000000A800EC00000AC0005EC303CC3000032A +:10451000CFFEA300000008A0000000005EE5000040 +:104520000000AEE800000000CAEC00000003A5EEA9 +:1045300000000008C0EE5000000AC0AE8000000C71 +:10454000805EC000003A503EE000008C000CE500A8 +:1045500000CFFFFFFA0000C80008EC0005A300032D +:10456000EE300AC00000CE500EC00000AFA0EFFC3D +:10457000000AFFFCAFFFFFFEC50005EC0008EE508F +:1045800005EC00008EA005EC00008EA005EC0000FC +:10459000AE8005EC000ACA0005EFFFFE800005ECC6 +:1045A0000005EC3005EC00005EC005EC00000EE5F7 +:1045B00005EC00000CE805EC00000EE505EC000041 +:1045C0005EE305EC0005EE80CFFFFFFEC5000003B3 +:1045D000AEFFEAA0005EE503AEE003EE30000AE3C2 +:1045E0000AFA000003A53EE3000000535EE000006D +:1045F00000008EC0000000008EC0000000008EC0D1 +:10460000000000005EE0000000003EE30000003318 +:104610000EE80000008508EC00000AC000AFC303EC +:10462000AC300005CFFEA300AFFFFFEA300005EC81 +:10463000005EE80005EC0003EE5005EC00008EC0C3 +:1046400005EC00003EE305EC00000EE505EC000083 +:104650000EE805EC00000CE805EC00000EE505ECAA +:1046600000000EE505EC00003EE005EC00008EC009 +:1046700005EC0003EE3005EC008EE500CFFFFFEA0D +:1046800030008EFFFFFFFE8003EE0000AEC003EEA1 +:10469000000008C003EE0000305303EE000380006A +:1046A00003EE000AE00003EFFFFFE00003EE000A64 +:1046B000E00003EE0005A00003EE0000300003EE72 +:1046C0000000000003EE0000008803EE000005A3D8 +:1046D00003EE00008EE08EFFFFFFFFA08EFFFFFFC6 +:1046E000FFC003EE00005EE303EE000003C803EE2C +:1046F0000000008803EE0000000003EE00008500CB +:1047000003EE0005A50003EFFFFFE50003EE000543 +:10471000A50003EE0000A50003EE0000530003EE29 +:104720000000000003EE0000000003EE00000000A7 +:10473000AFFFE50000000005CFFC8800008EC30835 +:10474000EE0005EE0000AE300CE500003A503EE011 +:10475000000005308EC000000000AFA00000000087 +:10476000AFA000000000AFA0005AAAA88EC0003879 +:10477000EFC55EE00000CE500EE50000CE5008EC24 +:104780000000CE5000CFA005EE500008EFFE8000E4 +:10479000AFFFA00CFFFA0AFA0000AE800AE80000A2 +:1047A000AE800AE80000AE800AE80000AE800AE8A9 +:1047B0000000AE800AE80000AE800AFFFFFFFE8026 +:1047C0000AE80000AE800AE80000AE800AE80000B7 +:1047D000AE800AE80000AE800AE80000AE800AE879 +:1047E0000000AE80CFFFC00CFFFC00CFFFFFFE003B +:1047F00000000EE3000000000EE3000000000EE3E6 +:10480000000000000EE3000000000EE300000000C6 +:104810000EE3000000000EE3000000000EE30000C5 +:1048200000000EE3000000000EE3000000000EE3B5 +:10483000000000000EE3000000000EE3000000CFC7 +:10484000FFFFFE000008EFFFFFFA0000008EA0004F +:104850000000008EA0000000008EA0000000008E6E +:10486000A0000000008EA0000000008EA00000004C +:10487000008EA0000000008EA0000000008EA000AE +:104880000000008EA0000000008EA0000000008E3E +:10489000A0000000008EA0000000008EA0005EE0DE +:1048A00000CE50008EE008EC00000AEFFC80000013 +:1048B000AFFFE35EFFE505EC0003EC3005EC000C18 +:1048C000C00005EC00CC000005EC0AC3000005ECBC +:1048D0008C50000005ECEFC0000005EFAEE50000D5 +:1048E00005EE08EC000005EC00CE800005EC005E53 +:1048F000E00005EC000CE80005EC0003EE0005EC20 +:104900000000CFA0AFFFE30AFFFC5EFFFA0000004B +:1049100000EE3000000000EE3000000000EE30003D +:10492000000000EE3000000000EE3000000000EE5D +:104930003000000000EE3000000000EE300000000B +:1049400000EE3000000000EE3000000000EE30000D +:1049500000A800EE300005A500EE30005EE08EFFFE +:10496000FFFFFFC0EFE50000CFFE0CFA0000EFC034 +:104970000CFC0005EFC00AEE0008CEC008CE500CBB +:10498000CEC008AE800C8EC0086EC05A6EC0085EE5 +:10499000E08C5EC0085CE3AA5EC0085AE8C85EC04E +:1049A0000855EA835EC00853EFC05EC00850CFA030 +:1049B0005EC00A50AE505EC0EFE85A0AFFFECFFA62 +:1049C0000003EFFE08EE30000AA008AFC000088028 +:1049D000088EE50008800888EE0008800880EE80D8 +:1049E000088008805EE0088008800CFA0880088053 +:1049F00005EE3880088000AFA8800880003EE8807F +:104A00000880000AFC8008800000EE8008A00000FA +:104A10008C80EFFE30000C800005CFFE8000008E01 +:104A2000C308EA0005EE0000AE800CE800003EE09E +:104A30003EE300000EE55EE000000CE85EE00000F2 +:104A40000AFA8EC000000AFA5EE000000AFA5EE090 +:104A500000000CE80EE300000EE50AE800003EE06E +:104A600003EE0000AE80008EC308EA000005CFFE12 +:104A700080008EFFFFFEC50003EE0003CE8003EE34 +:104A800000000EE303EE00000CE503EE00000CE571 +:104A900003EE00003EE303EE0005CE8003EFFFFFD0 +:104AA000C50003EE0000000003EE0000000003EE6E +:104AB0000000000003EE0000000003EE0000000014 +:104AC00003EE00000000AFFFE50000000008EFFE6D +:104AD000500000AFA00AEA0008EC0000AE500CE560 +:104AE00000005EC03EE300000EE35EE000000EE565 +:104AF0008EC000000CE88EC000000CE88EC00000E4 +:104B00000CE85EC000000CE53EE8EFC00EE50EECE0 +:104B100085EA3EE008EE00CE8C8000AFA08EFC005F +:104B20000005EFFFE0300000000EEAA000000005E5 +:104B3000EE808EFFFFFEC30003EE0008EE5003EE92 +:104B400000008EC003EE00005EE003EE00005EC0D9 +:104B500003EE00008EA003EE0008EE0003EFFFFE60 +:104B6000A00003EE05EC000003EE00CE800003EE93 +:104B7000005EE00003EE000CE80003EE0008EE002B +:104B800003EE0000EE808EFFE5008EFC003CEFFCA3 +:104B90008A0003CA303CFE000CE00000AE300EC0BC +:104BA00000003A500EE0000000000AFE5000000035 +:104BB000008EFEA3000000008EFEA0000000005C3E +:104BC000FC0000000000CE805A0000003EC03C8087 +:104BD00000000EC00EE300005C800CFE5005CC000F +:104BE00008A8EFFEA0000CFFFFFFFFA00EC33EE0F1 +:104BF0003CC03A503EE005A358003EE00083000070 +:104C00003EE0000000003EE0000000003EE000004A +:104C100000003EE0000000003EE0000000003EE03A +:104C2000000000003EE0000000003EE00000000048 +:104C30003EE0000000003EE00000000CFFFFA0008E +:104C4000CFFFC003EFFA0AE800000A500AE80000AC +:104C500008500AE8000008500AE8000008500AE876 +:104C6000000008500AE8000008500AE80000085058 +:104C70000AE8000008500AE8000008500AE80000AE +:104C800008500AE80000085008EA0000383000EE3A +:104C90008005CA00003AEFFC5000EFFFA005EFFAD4 +:104CA0000AFA00003A5005EC00005A0003EE00003A +:104CB000AA0000CE5000A500008EA005A300005E53 +:104CC000C008A000000EE30A8000000AE8383000A7 +:104CD0000008EA8A00000003EEAA00000000EEA52A +:104CE00000000000AFE0000000005EA00000000037 +:104CF0003A500000EFFCCFFE5EFE3EC00CE305A381 +:104D00003EC00CE308A00CE00AE50AA00AE30CE8A8 +:104D10000A8008C50EFA0A5005C83AEC383003EA92 +:104D20008AEE580000ECAACE8A0000CEA8AEA800F9 +:104D300000AEA58CC500008EE05EE300005EC03EC4 +:104D4000E000003EA00EC000000A500A80008EFF66 +:104D5000E00CFFE503EE0000AE3000AE8000A500E1 +:104D6000003EE00AA000000AE83830000003EEAA86 +:104D7000000000008EE3000000003EE5000000009F +:104D80008CEC00000000C8EE50000008C08EC0008F +:104D9000000A500EE500008C0005EC0003C800007E +:104DA000CE80AFFE800CFFFCAFFFE00AFFE808EC0E +:104DB00000008C5000EE3000AA00008EA005A30079 +:104DC000003EE00CC000000AE85A50000005EECE9C +:104DD00000000000CFE8000000008EE300000000AB +:104DE0003EE0000000003EE0000000003EE0000069 +:104DF00000003EE0000000003EE00000000CFFFF6D +:104E0000A00003EFFFFFFFE008EE50008C800CE0F5 +:104E10000000EC000530000AE3000000003EA000A6 +:104E2000000000CE0000000008C8000000000EC016 +:104E300000000000AE3000000003EA000000000C9B +:104E4000E0000000008C8000038300EC00000CC038 +:104E50000AE30003CFA03EFFFFFFFE500000CFFF9C +:104E6000FE300000CA0000000000CA000000000080 +:104E7000CA0000000000CA0000000000CA000000D4 +:104E80000000CA0000000000CA0000000000CA00C4 +:104E900000000000CA0000000000CA00000000007E +:104EA000CA0000000000CA0000000000CA000000A4 +:104EB0000000CA0000000000CA0000000000CA0094 +:104EC00000000000CA0000000000CA00000000004E +:104ED000CFFFFE3008C50000000000EA000000001F +:104EE000008C30000000003EA0000000000AE0003E +:104EF00000000005C80000000000CC000000000019 +:104F00008C50000000000EA0000000000AE300002A +:104F1000000003C80000000000AE00000000005CBC +:104F200080000000000CC00000000008C500000068 +:104F30000000EA0000000000AE30000000003C80ED +:104F4000000000000AE00CFFFFE50000000005A5DE +:104F50000000000005A50000000005A500000000FD +:104F600005A50000000005A50000000005A5000043 +:104F7000000005A50000000005A50000000005A533 +:104F80000000000005A50000000005A500000000CD +:104F900005A50000000005A50000000005A5000013 +:104FA000000005A50000000005A50000000005A503 +:104FB0000000000005A500000CFFFFE50000000058 +:104FC000EFE80000000AEACE3000005A3008A000E6 +:104FD000EFFFFFFFFFFC03AEE500000000005A807A +:104FE0000000005CEFFEA00008EC3008EA000AFABE +:104FF0000000EC0000000035EC00003AEFCAEC00C5 +:1050000005EE5000EC000EE30000EC005EE0000056 +:10501000EC000EE8005AEC8803CEFFC5AEE5038530 +:1050200000000000AEE80000000005C8000000001D +:1050300005C80000000005C80000000005C8000009 +:10504000000005C85EFFC30005CAC305EE3005EECB +:1050500030008EA005EA00005EC005C800003EE0FA +:1050600005C800003EE005C800005EC005EA00007B +:10507000AE8005CC8005EC0005A3CFFEA0000005A6 +:10508000CFFEA300008EC305EC0005EE0003EE305A +:105090000AE8000033000CE5000000000CE5000009 +:1050A00000000AE80000003005EC00000A8000AFB4 +:1050B000C303CC000008CFFEA3000000000358305B +:1050C0000000003CFE3000000000AE300000000098 +:1050D000AE3000000000AE3000000000AE3000082E +:1050E000EFFCAE3000AFA00AEE3005EC0000AE30B1 +:1050F0000AE80000AE300CE50000AE300CE5000020 +:10510000AE300AE50000AE3008EA0000EE3000CE16 +:10511000803AAFC5000AEFEAAC830005CFFEA000DD +:10512000008CA005EC0003EA00008C800AE500007A +:105130005EC00CFFFFFFFFC00CE5000000000AE8A6 +:105140000000000005EC00000A8000AEC303CC00A4 +:105150000005CFFEA000000005CFFEA000008CA03F +:105160000AFA0000EE0005850000EC0000000000D7 +:10517000EC0000000CFFFFFFFC000000EC00000052 +:105180000000EC0000000000EC0000000000EC005B +:1051900000000000EC0000000000EC000000000037 +:1051A000EC0000000000EC00000005EFFFFFC00075 +:1051B000000AEFFC8EE800CE503CE88505EA0003CB +:1051C000EC0005EA0003EC0000CE500AE500005CAC +:1051D000EFFC500003C80000000003EEA6330000FF +:1051E000008CCCEFFC300AC000003EC00EC00000B6 +:1051F0000EC00AEA3003AC80005CFFFEC50003AAC3 +:1052000000000000AEFA0000000003EA0000000009 +:1052100003EA0000000003EA0000000003EA0000C7 +:10522000000003EA5EFFC30003EAC503EE0003EEDD +:105230000000AE3003EA0000AE3003EA0000AE30FA +:1052400003EA0000AE3003EA0000AE3003EA0000DB +:10525000AE3003EA0000AE308EFFE00EFFE8000043 +:105260003EE5000000003EE50000000000000000F8 +:1052700000000000000000000350000000AFEFE05D +:10528000000000000EE0000000000EE00000000042 +:105290000EE0000000000EE0000000000EE0000044 +:1052A00000000EE0000000000EE0000000000EE034 +:1052B000000000AFFFFFFA000000000CFC0000003F +:1052C000000CFC00000000000000000000000000D6 +:1052D00000000003550000000EEEE800000000058D +:1052E000C80000000005C80000000005C80000005C +:1052F0000005C80000000005C80000000005C80047 +:1053000000000005C80000000005C80000000005FE +:10531000C80000300008C50005EE305CA00000AEFB +:10532000FFC5000003AA000000008EFC0000000082 +:1053300003EC0000000003EC0000000003EC0000A0 +:10534000000003EC0000000003EC00CFFFC003EC02 +:10535000000CC30003EC00CC000003EC0CC0000008 +:1053600003ECCFE3000003EE88EE000003EC00AF97 +:10537000A00003EC000CE80003EC0003EE305EFF3D +:10538000E00EFFFA00035CC0000000ACCFE00000BC +:1053900000000EE0000000000EE0000000000EE043 +:1053A000000000000EE0000000000EE00000000021 +:1053B0000EE0000000000EE0000000000EE0000023 +:1053C00000000EE0000000000EE0000000000EE013 +:1053D000000000000EE0000000000EE0000000CF22 +:1053E000FFFFFC00033000000000CFCCFE8AEFC0BE +:1053F0000EE80EEA0AE50EC00CE30AE50EC00CE367 +:105400000AE50EC00CE30AE50EC00CE30AE50EC087 +:105410000CE30AE50EC00CE30AE50EC00CE30AE556 +:10542000EFFCCFFE8EFE3ACA5CFFC30038EAC5032C +:10543000EE0003EE3000AE3003EA0000AE3003EAC7 +:105440000000AE3003EA0000AE3003EA0000AE30E8 +:1054500003EA0000AE3003EA0000AE308EFFE00E3B +:10546000FFE80008EFFE800000CEA00AEC0008EA8A +:105470000000AE800EE300003EE03EE000000EE3E0 +:105480003EE000000EE30EE300003EE008C800002E +:105490008EA000CE8008EC000008EFFE80008ACAD3 +:1054A0008EFEC3003AEAC505EE5003EE00005EC072 +:1054B00003EA00000EE003EA00000EE303EA000046 +:1054C0000EE303EA00003EE003EC00008EA003ECD4 +:1054D000A008EE0003EAAEFEA00003EA0000000010 +:1054E00003EA00000000AFFFE30000000008EFEA5D +:1054F000383000CEA00ACE3008EA0000CE300CE5ED +:105500000000CE300EE30000CE300EE30000CE30BF +:105510000EE30000CE300AE80000CE3000EE503A34 +:10552000EE30003AEFEACE3000000000CE3000004E +:105530000000CE300000005EFFE83AACE03CFFC067 +:10554000356EE5A83EE3000CE8300330000CE500C2 +:105550000000000CE0000000000CE0000000000C67 +:10556000E0000000000CE0000000000CE000000083 +:105570008EFFFFFC0000000AEFFEAC0000CE5008DA +:10558000EE0000EA00008C3000CE50000530003AFA +:10559000EEC50000000005CEE80008A00000AE50F7 +:1055A00005A500003C8005EE5003AE3003CAEFFFB6 +:1055B000C50000005800000000008A000000000044 +:1055C000CC0000000008EC0000000AFFFFFFFC0018 +:1055D0000000EC0000000000EC0000000000EC0007 +:1055E00000000000EC0000000000EC0000000000E3 +:1055F000EC0000000000EE0008800000AE505A30C1 +:1056000000000CFFE500008800003830AFE8003EE5 +:10561000FE3005C80000CE3005C80000CE3005C8F9 +:105620000000CE3005C80000CE3005C80000CE30E6 +:1056300005C80000CE3005EA0000EE3000EE503C18 +:10564000CFC5005EFFE8CC838EFFE008EFE503EEF8 +:1056500000008C3000CE3000A800005EA005A30042 +:10566000000EE30CA000000AFA5A50000003EEAC52 +:1056700000000000CFE8000000005EE00000000035 +:105680000EA00000EFFAEFFA8EFE3EC00EE008C357 +:105690000CE00CE30AA00AE50EE80A5005C85AEC33 +:1056A0005A0000ECACEECC0000CEC8AEC800008EB4 +:1056B000E38EE300003EC03EC000000C800CA00062 +:1056C0000EFFFC5EFFE0005EE003A500000AE80AB2 +:1056D000A0000000CEAA000000003EE30000000091 +:1056E0003CEA00000000A5AE8000000A800EE30046 +:1056F00000AC0005EC308EFFC08EFFE55EFFE53E9E +:10570000FFE800CE5000CC30005C8003A500000E06 +:10571000E008C0000008C50CA0000003EC5A5000CF +:105720000000AEAC000000005EE8000000000CE3EA +:10573000000000000AA0000000003A5000000385AD +:10574000AA00000008EFC000000005EFFFFFFE30D8 +:1057500008EA0008EA0008C0005EC000088003EE06 +:10576000000000000EE300000000CE500000000A20 +:10577000E8000AA0008EA0000C8005EC0003CE50CB +:105780000CFFFFFFFE3000000003CE800000000C85 +:10579000C3000000003A50000000003A5000000032 +:1057A000003A50000000003A50000000003A50005B +:1057B0000000003A50000000005A3000000003CC06 +:1057C000000000003CA00000000000CC0000000031 +:1057D000005A30000000003A50000000003A50002B +:1057E0000000003A50000000003A50000000003A6B +:1057F00050000000000EC30000000005CE80000035 +:105800000880000000000880000000000880000000 +:1058100000000880000000000880000000000880F0 +:105820000000000008800000000008800000000068 +:1058300008800000000008800000000008800000D0 +:1058400000000880000000000880000000000880C0 +:105850000000000008800000000008800000000038 +:1058600008800000000008800000000008800000A0 +:105870000000088000000000088000000000088090 +:10588000000000000880000008EC30000000000C60 +:10589000C00000000005A30000000005A3000000F8 +:1058A0000005A30000000005A30000000005A30000 +:1058B00000000005A30000000003A5000000000098 +:1058C0008A30000000005EE300000003EC000000EE +:1058D0000005A50000000005A30000000005A300CE +:1058E00000000005A30000000005A3000000000563 +:1058F000A3000000000CE000000008EC50000000D5 +:1059000003CFEA0000000A80CFC00088580008ECEE +:1059100035A00000005EFE5000000000C000000046 +:105920000C00000000000000C00010000C0000038C +:1059300060000000C00006000C00000F84000000A2 +:10594000C00010000C000003E4000000C0001500BF +:105950000C00000062010000C00010000C000003F9 +:10596000C2010000C00010000C0000032202000071 +:10597000C00006000C00000F46020000C000150029 +:105980000C000001C4020000C00015000C00000162 +:1059900042030000C0000C000C0000058A03000058 +:1059A000C0000B000C000006CC030000C000060085 +:1059B0000C000000F0030000C00001000C00000B10 +:1059C000F6030000C00003000C0000030804000000 +:1059D000C00014000C00000180040000C000100092 +:1059E0000C000003E0040000C00010000C000003E5 +:1059F00040050000C00010000C000003A0050000DE +:105A0000C00010000C00000300060000C0001000E1 +:105A10000C00000360060000C00010000C00000332 +:105A2000C0060000C00010000C00000320070000AA +:105A3000C00010000C00000380070000C000100030 +:105A40000C000003E0070000C00010000C00000381 +:105A500040080000C0000B000C000003820800009A +:105A6000C0000C000C000001CA080000C0001000BB +:105A70000C0000032A090000C00005000C0000090A +:105A800048090000C00010000C000003A809000035 +:105A9000C00010000C000003080A0000C000100045 +:105AA0000C000003680A0000C00010000C00000396 +:105AB000C80A0000C0000F000C000003220B000009 +:105AC000C0000F000C0000037C0B0000C0000F00A2 +:105AD0000C000003D60B0000C0000F000C000003F8 +:105AE000300C0000C0000F000C0000038A0C000006 +:105AF000C0000F000C000003E40C0000C0000F0009 +:105B00000C0000033E0D0000C0000F000C0000035D +:105B1000980D0000C00012000C000000040E0000F0 +:105B2000C0000F000C0000035E0E0000C0000F005C +:105B30000C000003B80E0000C0000F000C000003B2 +:105B4000120F0000C0000F000C0000036C0F0000DB +:105B5000C0000F000C000003C60F0000C0000F00C3 +:105B60000C00000320100000C00011000C00000118 +:105B700086100000C0000F000C000003E0100000C1 +:105B8000C0000F000C0000033A110000C0000F001D +:105B90000C00000394110000C0000F000C00000373 +:105BA000EE110000C0000F000C00000348120000BE +:105BB000C0000F000C000003A2120000C0000F0084 +:105BC0000C000003FC120000C0000F000C000003DA +:105BD00056130000C0000F000C000003B0130000BB +:105BE000C00014000C00000128140000C0001300C5 +:105BF0000C0000019A140000C00014000C00000109 +:105C000012150000C00003000C0000132415000052 +:105C1000C00001000C0000002A150000C0000200B6 +:105C20000C00001336150000C0000A000C00000331 +:105C300072150000C00010000C000003D215000017 +:105C4000C0000A000C0000030E160000C000100087 +:105C50000C0000036E160000C0000A000C000003D8 +:105C6000AA160000C0000F000C000003041700007B +:105C7000C0000D000C00000052170000C000100012 +:105C80000C000003B2170000C0000F000C0000035E +:105C90000C180000C00012000C0000007818000072 +:105CA000C00010000C000003D8180000C000100055 +:105CB0000C00000338190000C0000B000C000003AA +:105CC0007A190000C0000A000C000003B619000099 +:105CD000C0000A000C000003F2190000C0000D0013 +:105CE0000C000000401A0000C0000D000C00000075 +:105CF0008E1A0000C0000A000C000003CA1A00003F +:105D0000C0000A000C000003061B0000C0000E00CB +:105D10000C0000035A1B0000C0000B000C00000325 +:105D20009C1B0000C0000A000C000003D81B0000F0 +:105D3000C0000A000C000003141C0000C0000A0090 +:105D40000C000003501C0000C0000D000C000000FF +:105D50009E1C0000C0000A000C000003DA1C0000BA +:105D6000C00014000C000001521D0000C00017000C +:105D70000C000000DC1D0000C00014000C0000013D +:105D8000541E0000C00004000C0000126C1E000035 +:105D9000C00000000C0000002000000060000000B7 +:105DA0000000000000000000AC3A0108185901088A +:105DB00060001700985D0108010000000000040069 +:105DC00073676C5F6C6162656C5F636F6E73747236 +:105DD0007563745F6362000064656661756C74541A +:105DE00061736B002123242728292A2B2C2D2E3088 +:105DF0003132333435363738000000002123242770 +:105E000028292A2B2C2D2E30313233343536373891 +:105E100039000000303132333435363738393A3BC7 +:105E20003C3D3E3F40000000414243444546474818 +:105E3000494A4B4C4D4E4F505152535400000000B4 +:105E400053544D33322053474C20546578742044CA +:105E5000656D6F000D0A436F6D6D616E64204C6956 +:105E600073743A0D0A0000000D0A566172204C69E5 +:105E700073743A0D0A0000000D0A55736572204CC8 +:105E80006973743A0D0A00000D0A4B6579204C695C +:105E900073743A0D0A000000436F6D6D616E6420EB +:105EA0006E6F7420466F756E640D0A000D0A57619F +:105EB000726E696E673A20436F6D6D616E64206922 +:105EC0007320746F6F206C6F6E670D0A0000000006 +:105ED000206973206E6F742061207661720D0A0054 +:105EE00063616E2774207365742072656164206F2E +:105EF0006E6C79207661720D0A00000063616E2776 +:105F0000742073657420706F696E7465720D0A0079 +:105F10000D0A205F2020202020202020205F20202C +:105F2000205F202020202020202020202020202032 +:105F3000202020205F202020202020202020205FE3 +:105F4000205F200D0A7C207C202020205F5F5F7C6A +:105F5000207C5F7C207C5F205F5F5F205F205F5F35 +:105F60002020205F5F5F7C207C5F5F2020205F5FC0 +:105F70005F7C207C207C0D0A7C207C2020202F2030 +:105F80005F205C205F5F7C205F5F2F205F205C20B4 +:105F9000275F5F7C202F205F5F7C20275F205C20B5 +:105FA0002F205F205C207C207C0D0A7C207C5F5FA2 +:105FB0007C20205F5F2F207C5F7C207C7C20205F0A +:105FC0005F2F207C202020205C5F5F205C207C20D5 +:105FD0007C207C20205F5F2F207C207C0D0A7C5F52 +:105FE0005F5F5F5F5C5F5F5F7C5C5F5F7C5C5F5F90 +:105FF0005C5F5F5F7C5F7C202020207C5F5F5F2F89 +:106000005F7C207C5F7C5C5F5F5F7C5F7C5F7C0D86 +:106010000A0D0A4275696C643A2020202020202055 +:106020004D617220313920323032362031333A35E9 +:10603000323A31390D0A56657273696F6E3A202013 +:10604000202020332E322E340D0A436F707972696E +:106050006768743A202020286329203230323020AB +:106060004C65747465720D0A000000000D0A7061C1 +:106070007373776F7264206572726F720D0A00001D +:10608000566172206E6F7420466F756E740D0A0033 +:106090001B5B324B0D000000434D4420000000000C +:1060A00056415220000000004B45592000000000DE +:1060B000636F6D6D616E642068656C70206F662023 +:1060C00000000000506C6561736520696E70757426 +:1060D0002070617373776F72643A00004E4F4E45C3 +:1060E000000000001B5B324A1B5B314800000000CF +:1060F000555345520000000073676C5F7365617211 +:1061000063685F756E69636F64655F63685F696E1E +:106110006465783A205B307825785D756E69636FC9 +:106120006465206E6F7420666F756E6420696E20E2 +:10613000666F6E74207461626C6500008C62010889 +:10614000000000205402000074090008D863010810 +:1061500054020020EC5301005C900008D863010851 +:1061600000C00120004000005C9000080008000012 +:106170009C2F0108A32F0108A42F01080021000073 +:10618000B12F0108950C0108B82F01080009000083 +:1061900000415B1B7B110108C02F010800090000B2 +:1061A00000425B1B65FE0008C32F010800190000B8 +:1061B00000435B1BEF0A0108C82F0108001900000B +:1061C00000445B1BDB070108CE2F0108000900001B +:1061D00000000009B90F0108D32F010800190000C1 +:1061E0000000000875FC0008D72F01080019000006 +:1061F0000000007F75FC0008E12F01080019000075 +:106200007E335B1B5BFD0008EB2F010800190000CB +:106210000000000A75FE0008F22F010800190000B6 +:106220000000000D75FE0008F82F01080020000096 +:10623000FE2F0108C90401080330010800210000F5 +:1062400021300108891101082730010800210000D0 +:106250003530010849FD00083A30010800210000EE +:10626000473001089B1101084C3001080021000053 +:1062700059300108C90701085E30010800210000FB +:106280006B30010805FD00087130010881321042B1 +:1062900001035D24F41AAA0101141E405E010828BE +:1062A000041A14045EE45D0108FC04290C29142975 +:1062B0001C29248113C1AC1408ADAD140820581258 +:1062C0002016C0012020D81C2020F80C69C8B1136A +:1062D000316E1B0879041A89041AB5041AF50413DF +:1062E000FD6D1B08410813120114020202164083BF +:1062F0000440571D020102033D071A040309041A52 +:106300000313090B1B08050413C10A1B082D081AE7 +:10631000510441130A062A02CB298013E1681408AC +:10632000DD664C082B6B1C13B1671408D1651B0884 +:106330009514C11A55281A11041A9D041A01041C37 +:1063400009024387111DC0320904C91A020B130543 +:106350002416100105240110090104240202052459 +:1063600006170107058203081C100904BD320A2E16 +:106370000705010240072A810724810182180A10BB +:106380005F0108AC5E010854041A68041A78041A04 +:1063900088041A98041AFC041AE0041AD0041E8017 +:1063A000600108B0041AC4041A6C041AE4041A90B8 +:1063B000041A98041AA0041AF0041AA8041ADC0497 +:1063C000031622221E482F01084E0417C6E533B4D7 +:0863D000919502000800000095 :040000050800018965 :00000001FF diff --git a/User/application/app.c b/User/application/app.c index 26cabd6..f8cdcd0 100644 --- a/User/application/app.c +++ b/User/application/app.c @@ -2,18 +2,38 @@ #include "board.h" #include "os.h" #include "shell_port.h" +#include "../system/sgl/sgl.h" static TaskHandle_t business_task_handle = NULL; +void sgl_print_hello(void) +{ + /* 设置页é¢èƒŒæ™¯ä¸ºé»‘色,使白色文字å¯è§ */ + sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00)); + + /* å…¨å± label,居中显示 Hello World */ + sgl_obj_t *label = sgl_label_create(NULL); + sgl_obj_set_pos(label, 0, 0); + sgl_obj_set_size(label, 240, 240); + sgl_label_set_text(label, "Hello World"); + sgl_label_set_font(label, &song23); + sgl_label_set_text_color(label, sgl_rgb(0xFF, 0xFF, 0xFF)); + sgl_label_set_text_align(label, SGL_ALIGN_CENTER); +} + void business_task(void *pvParameters) { + /* å¯åŠ¨æ—¶æ˜¾ç¤º Hello World 2 ç§’ */ + sgl_print_hello(); + sgl_task_handle(); + vTaskDelay(2000); + for (;;) { rtc_update(); lcd_rtc_test(); + sgl_task_handle(); led_toggle(LED_USER); - // usb_printf("STM32F103 usb test\r\n"); - // usb_printf("print test >>>>>>\r\n"); vTaskDelay(1000); } } diff --git a/User/board/board.c b/User/board/board.c index 88f15e1..729bcdd 100644 --- a/User/board/board.c +++ b/User/board/board.c @@ -3,10 +3,21 @@ #include "main.h" #include "rtc.h" #include "spi.h" - - +#include "../system/sgl/sgl.h" +#include "os.h" board_t board; +#define SGL_PANEL_WIDTH 240 +#define SGL_PANEL_HEIGHT 240 + +static sgl_color_t sgl_panel_buffer[SGL_PANEL_WIDTH * 10]; + +static void sgl_flush_area(sgl_area_t *area, sgl_color_t *src) +{ + board.lcd->driver.write_pixels(board.lcd, area->x1, area->y1, area->x2, area->y2, (uint16_t *)src); + sgl_fbdev_flush_ready(); +} + void led_open(led_e led) { switch (led) @@ -138,119 +149,141 @@ BOOL rtc_init(void) void lcd_rtc_test(void) { - char buf[128] = {0}; // »º³åÇø - board.lcd->driver.set_hz_font(board.lcd, &ch_font_24); // ÉèÖúº×Ö×ÖÌå - board.lcd->driver.full_fill(board.lcd, LCD_BLACK); // ÉèÖñ³¾°É« - board.lcd->driver.set_color(board.lcd, LCD_WHITE); // ÉèÖû­±ÊÑÕÉ« - uint8_t hight_offset = 70; - board.lcd->driver.set_color(board.lcd, LIGHT_BLUE); // ÉèÖû­±ÊÑÕÉ« - board.lcd->driver.display_text(board.lcd, 13, hight_offset, "STM32 RTC²âÊÔ"); - board.lcd->driver.set_color(board.lcd, LIGHT_YELLOW); // ÉèÖû­±ÊÑÕÉ« - board.lcd->driver.display_text(board.lcd, 13, hight_offset + board.lcd->info.hz_font->height, "ÆÁÄ»·Ö±æÂÊ:240*240"); - board.lcd->driver.set_color(board.lcd, LIGHT_RED); // ÉèÖû­±ÊÑÕÉ« - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20); - sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 2000 + board.rtc_date.year, board.rtc_date.month, board.rtc_date.day, board.rtc_time.hour, board.rtc_time.minute, board.rtc_time.second); - board.lcd->driver.display_text(board.lcd, 13, hight_offset + board.lcd->info.hz_font->height * 2, buf); + static sgl_obj_t *label_time = NULL; + static char buf[32]; + + if (label_time == NULL) + { + sgl_obj_delete(NULL); + sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00)); + + sgl_obj_t *lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 70); + sgl_obj_set_size(lbl, 240, 28); + sgl_label_set_text(lbl, "STM32 RTC Test"); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xAA, 0xFF)); + sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); + + lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 100); + sgl_obj_set_size(lbl, 240, 28); + sgl_label_set_text(lbl, "Resolution: 240x240"); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0x00)); + sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); + + label_time = sgl_label_create(NULL); + sgl_obj_set_pos(label_time, 0, 130); + sgl_obj_set_size(label_time, 240, 28); + sgl_label_set_font(label_time, &song23); + sgl_label_set_text_color(label_time, sgl_rgb(0xFF, 0x40, 0x40)); + sgl_label_set_text_align(label_time, SGL_ALIGN_CENTER); + } + + sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", + 2000 + board.rtc_date.year, board.rtc_date.month, board.rtc_date.day, + board.rtc_time.hour, board.rtc_time.minute, board.rtc_time.second); + sgl_label_set_text(label_time, buf); } // ÇåÆÁ²âÊÔ void lcd_test_clear(void) { - uint8_t i = 0; // ¼ÆÊý±äÁ¿ - board.lcd->driver.set_hz_font(board.lcd, &ch_font_24); // ÉèÖúº×Ö×ÖÌå - board.lcd->driver.set_color(board.lcd, LCD_BLACK); // ÉèÖû­±ÊÑÕÉ« + sgl_color_t bg_colors[8]; + bg_colors[0] = sgl_rgb(0xFF, 0x80, 0x80); /* LIGHT_RED */ + bg_colors[1] = sgl_rgb(0x80, 0xFF, 0x80); /* LIGHT_GREEN */ + bg_colors[2] = sgl_rgb(0x80, 0x80, 0xFF); /* LIGHT_BLUE */ + bg_colors[3] = sgl_rgb(0xFF, 0xFF, 0x80); /* LIGHT_YELLOW */ + bg_colors[4] = sgl_rgb(0x80, 0xFF, 0xFF); /* LIGHT_CYAN */ + bg_colors[5] = sgl_rgb(0xA3, 0xA3, 0xA3); /* LIGHT_GREY */ + bg_colors[6] = sgl_rgb(0xFF, 0x80, 0xFF); /* LIGHT_MAGENTA */ + bg_colors[7] = sgl_rgb(0xFF, 0xFF, 0xFF); /* LCD_WHITE */ - for (i = 0; i < 8; i++) + sgl_obj_delete(NULL); + + sgl_obj_t *lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 70); + sgl_obj_set_size(lbl, 240, 28); + sgl_label_set_text(lbl, "STM32 Clear Test"); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); + sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); + + lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 100); + sgl_obj_set_size(lbl, 240, 28); + sgl_label_set_text(lbl, "Resolution: 240x240"); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); + sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); + + lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 130); + sgl_obj_set_size(lbl, 240, 28); + sgl_label_set_text(lbl, "Controller: ST7789"); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); + sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); + + for (uint8_t i = 0; i < 8; i++) { - switch (i) // Çл»±³¾°É« - { - case 0: - board.lcd->driver.full_fill(board.lcd, LIGHT_RED); - break; - case 1: - board.lcd->driver.full_fill(board.lcd, LIGHT_GREEN); - break; - case 2: - board.lcd->driver.full_fill(board.lcd, LIGHT_BLUE); - break; - case 3: - board.lcd->driver.full_fill(board.lcd, LIGHT_YELLOW); - break; - case 4: - board.lcd->driver.full_fill(board.lcd, LIGHT_CYAN); - break; - case 5: - board.lcd->driver.full_fill(board.lcd, LIGHT_GREY); - break; - case 6: - board.lcd->driver.full_fill(board.lcd, LIGHT_MAGENTA); - break; - case 7: - board.lcd->driver.full_fill(board.lcd, LCD_WHITE); - break; - default: - break; - } - board.lcd->driver.clear(board.lcd); // ÇåÆÁ - board.lcd->driver.display_text(board.lcd, 13, 70, "STM32 Ë¢ÆÁ²âÊÔ"); - board.lcd->driver.display_text(board.lcd, 13, 106, "ÆÁÄ»·Ö±æÂÊ:240*240"); - board.lcd->driver.display_text(board.lcd, 13, 142, "¿ØÖÆÆ÷:ST7789"); - HAL_Delay(1000); // ÑÓʱ + sgl_page_set_color(sgl_screen_act(), bg_colors[i]); + sgl_task_handle(); + vTaskDelay(1000); } + + sgl_obj_delete(NULL); } // Îı¾²âÊÔ void lcd_test_text(void) { - board.lcd->driver.clear(board.lcd); // ÇåÆÁ - board.lcd->driver.full_fill(board.lcd, LCD_BLACK); + static uint8_t initialized = 0; + if (initialized) + return; + initialized = 1; - board.lcd->driver.set_color(board.lcd, LCD_WHITE); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_32); - board.lcd->driver.display_text(board.lcd, 0, 0, "!#$'()*+,-.0123"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_24); - board.lcd->driver.display_text(board.lcd, 0, 32, "!#$'()*+,-.012345678"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20); - board.lcd->driver.display_text(board.lcd, 0, 56, "!#$'()*+,-.0123456789:;<"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_16); - board.lcd->driver.display_text(board.lcd, 0, 76, "!#$'()*+,-.0123456789:;<=>?@AB"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_12); - board.lcd->driver.display_text(board.lcd, 0, 92, "!#$'()*+,-.0123456789:;<=>?@ABCDEFGHIJKL"); + sgl_obj_delete(NULL); + sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00)); - board.lcd->driver.set_color(board.lcd, LCD_CYAN); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_12); - board.lcd->driver.display_text(board.lcd, 0, 104, "!#&'()*+,-.0123456789:;<=>?@ABCDEFGHIJKL"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_16); - board.lcd->driver.display_text(board.lcd, 0, 116, "!#&'()*+,-.0123456789:;<=>?@AB"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_20); - board.lcd->driver.display_text(board.lcd, 0, 132, "!#&'()*+,-.0123456789:;<"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_24); - board.lcd->driver.display_text(board.lcd, 0, 152, "!#&'()*+,-.012345678"); - board.lcd->driver.set_asscii_font(board.lcd, &ascii_font_32); - board.lcd->driver.display_text(board.lcd, 0, 176, "!#&'()*+,-.0123"); + /* 5 rows of white text */ + static const char *white_lines[5] = { + "STM32 SGL Text Demo", + "ABCDEFGHIJKLMNOPQRST", + "0123456789:;<=>?@", + "!#$'()*+,-.012345678", + "!#$'()*+,-.0123456789", + }; + for (uint8_t i = 0; i < 5; i++) + { + sgl_obj_t *lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, i * 24); + sgl_obj_set_size(lbl, 240, 24); + sgl_label_set_text(lbl, white_lines[i]); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0xFF)); + } + + /* 5 rows of cyan text */ + static const char *cyan_lines[5] = { + "!#$'()*+,-.0123456789", + "!#$'()*+,-.012345678", + "0123456789:;<=>?@", + "ABCDEFGHIJKLMNOPQRST", + "STM32 SGL Text Demo", + }; + for (uint8_t i = 0; i < 5; i++) + { + sgl_obj_t *lbl = sgl_label_create(NULL); + sgl_obj_set_pos(lbl, 0, 120 + i * 24); + sgl_obj_set_size(lbl, 240, 24); + sgl_label_set_text(lbl, cyan_lines[i]); + sgl_label_set_font(lbl, &song23); + sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xFF, 0xFF)); + } } -// ±äÁ¿²âÊÔ£¬°üÀ¨ÕûÊýºÍСÊý -void lcd_test_var(void) -{ -} - -// ÑÕÉ«²âÊÔ -void lcd_test_color(void) -{ -} - -// 2DͼÐλæÖÆ -void lcd_test_2d(void) -{ -} - -// ͼƬÏÔʾ -void lcd_test_image(void) -{ -} - - void lcd_init(void) { spi_gpio_group_t gpios; @@ -277,6 +310,17 @@ void lcd_init(void) // lcd_test_clear(); // lcd_test_text(); + + /* SGL³õʼ»¯ */ + sgl_fbinfo_t fbinfo = { + .xres = SGL_PANEL_WIDTH, + .yres = SGL_PANEL_HEIGHT, + .flush_area = sgl_flush_area, + .buffer[0] = sgl_panel_buffer, + .buffer_size = sizeof(sgl_panel_buffer) / sizeof(sgl_color_t), + }; + sgl_fbdev_register(&fbinfo); + sgl_init(); } /** diff --git a/User/system/lib/lcd/lcd_tft_154.c b/User/system/lib/lcd/lcd_tft_154.c index d0a20db..2d15f4b 100644 --- a/User/system/lib/lcd/lcd_tft_154.c +++ b/User/system/lib/lcd/lcd_tft_154.c @@ -1,15 +1,5 @@ #include "lcd_tft_154.h" -#define FILL_ZERO 0 // å¡«å……0 -#define FILL_SPACE 1 // 填充空格 - -// 因为这类SPIçš„å±å¹•ï¼Œæ¯æ¬¡æ›´æ–°æ˜¾ç¤ºæ—¶ï¼Œéœ€è¦å…ˆé…ç½®åæ ‡åŒºåŸŸã€å†å†™æ˜¾å­˜ï¼Œ -// åœ¨æ˜¾ç¤ºå­—ç¬¦æ—¶ï¼Œå¦‚æžœæ˜¯ä¸€ä¸ªä¸ªç‚¹åŽ»å†™åæ ‡å†™æ˜¾å­˜ï¼Œä¼šéžå¸¸æ…¢ï¼Œ -// å› æ­¤å¼€è¾Ÿä¸€ç‰‡ç¼“å†²åŒºï¼Œå…ˆå°†éœ€è¦æ˜¾ç¤ºçš„æ•°æ®å†™è¿›ç¼“冲区,最åŽå†æ‰¹é‡å†™å…¥æ˜¾å­˜ã€‚ -// 用户å¯ä»¥æ ¹æ®å®žé™…情况去修改此处缓冲区的大å°ï¼Œ -// ä¾‹å¦‚ï¼Œç”¨æˆ·éœ€è¦æ˜¾ç¤º32*32的汉字时,需è¦çš„大å°ä¸º 32*32*2 = 2048 字节(æ¯ä¸ªåƒç´ ç‚¹å 2字节) -static uint16_t *pri; // 显示缓存 - // ç­‰å¾…é€šè®¯å®Œæˆ static void _wait_finish(spi_t *lcd_spi) { @@ -113,16 +103,6 @@ static void _set_dir(lcd_t *lcd, uint8_t scan_dir) lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs); } -// 设置画笔颜色 -static void _set_color(lcd_t *lcd, uint32_t color) -{ - uint16_t red_value = 0, green_value = 0, blue_value = 0; // å„个颜色通é“的值 - red_value = (uint16_t)((color & 0x00F80000) >> 8); // è½¬æ¢æˆ 16ä½ çš„RGB565颜色 - green_value = (uint16_t)((color & 0x0000FC00) >> 5); - blue_value = (uint16_t)((color & 0x000000F8) >> 3); - lcd->info.color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD傿•° -} - static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs); @@ -141,166 +121,12 @@ static void _set_address(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs); } -static void _set_asscii_font(lcd_t *lcd, lcd_font *font) +// 写åƒç´ ç¼“冲区 +static void _write_pixels(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *data) { - lcd->info.ascii_font = font; -} - -static void _set_hz_font(lcd_t *lcd, lcd_font *font) -{ - lcd->info.hz_font = font; - switch (font->width) - { - case 12: - lcd->driver.set_asscii_font(lcd, &ascii_font_12); - break; // 设置ASCII字符的字体为 1206 - case 16: - lcd->driver.set_asscii_font(lcd, &ascii_font_16); - break; // 设置ASCII字符的字体为 1608 - case 20: - lcd->driver.set_asscii_font(lcd, &ascii_font_20); - break; // 设置ASCII字符的字体为 2010 - case 24: - lcd->driver.set_asscii_font(lcd, &ascii_font_24); - break; // 设置ASCII字符的字体为 2412 - case 32: - lcd->driver.set_asscii_font(lcd, &ascii_font_32); - break; // 设置ASCII字符的字体为 3216 - default: - break; - } -} - -/**************************************************************************************************************************************** - * 函 æ•° å: LCD_DisplayChar - * - * å…¥å£å‚æ•°: x - èµ·å§‹æ°´å¹³åæ ‡ - * y - èµ·å§‹åž‚ç›´åæ ‡ - * c - ASCII字符 - * - * 函数功能: åœ¨æŒ‡å®šåæ ‡æ˜¾ç¤ºæŒ‡å®šçš„字符 - * - * 说 明: 1. å¯è®¾ç½®è¦æ˜¾ç¤ºçš„字体,例如使用 LCD_SetAsciiFont(&ASCII_Font24) 设置为 2412çš„ASCII字体 - * 2. å¯è®¾ç½®è¦æ˜¾ç¤ºçš„颜色,例如使用 LCD_SetColor(0xff0000FF) 设置为è“色 - * 3. å¯è®¾ç½®å¯¹åº”的背景色,例如使用 LCD_SetBackColor(0x000000) 设置为黑色的背景色 - * 4. 使用示例 LCD_DisplayChar( 10, 10, 'a') ï¼Œåœ¨åæ ‡(10,10)显示字符 'a' - * - *****************************************************************************************************************************************/ - -void _display_char(lcd_t *lcd, uint16_t x, uint16_t y, uint8_t c) -{ - uint16_t index = 0, counter = 0, i = 0, w = 0; // 计数å˜é‡ - uint8_t disChar; // å­˜å‚¨å­—ç¬¦çš„åœ°å€ - - c = c - 32; // 计算ASCII字符的åç§» - - lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs); - - for (index = 0; index < lcd->info.ascii_font->sizes; index++) - { - disChar = lcd->info.ascii_font->table[c * lcd->info.ascii_font->sizes + index]; // 获å–字符的模值 - for (counter = 0; counter < 8; counter++) - { - if (disChar & 0x01) - { - pri[i] = lcd->info.color; // 当剿¨¡å€¼ä¸ä¸º0时,使用画笔色绘点 - } - else - { - pri[i] = lcd->info.back_color; // å¦åˆ™ä½¿ç”¨èƒŒæ™¯è‰²ç»˜åˆ¶ç‚¹ - } - disChar >>= 1; - i++; - w++; - if (w == lcd->info.ascii_font->width) // 如果写入的数æ®è¾¾åˆ°äº†å­—符宽度,则退出当å‰å¾ªçޝ - { // 进入下一字符的写入的绘制 - w = 0; - break; - } - } - } - lcd->driver.set_address(lcd, x, y, x + lcd->info.ascii_font->width - 1, y + lcd->info.ascii_font->height - 1); // è®¾ç½®åæ ‡ - _write_buff(lcd, pri, lcd->info.ascii_font->width * lcd->info.ascii_font->height); // 写入显存 -} - -void _display_chinese(lcd_t *lcd, uint16_t x, uint16_t y, char *text) -{ - uint16_t i = 0, index = 0, counter = 0; // 计数å˜é‡ - uint16_t addr; // å­—æ¨¡åœ°å€ - uint8_t disChar; // 字模的值 - uint16_t Xaddress = 0; // æ°´å¹³åæ ‡ - - while (1) - { - // 对比数组中的汉字编ç ï¼Œç”¨ä»¥å®šä½è¯¥æ±‰å­—å­—æ¨¡çš„åœ°å€ - if (*(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 0) == *text && *(lcd->info.hz_font->table + (i + 1) * lcd->info.hz_font->sizes + 1) == *(text + 1)) - { - addr = i; // 字模地å€åç§» - break; - } - i += 2; // æ¯ä¸ªä¸­æ–‡å­—符编ç å ä¸¤å­—节 - - if (i >= lcd->info.hz_font->table_rows) - break; // 字模列表中无相应的汉字 - } - i = 0; - for (index = 0; index < lcd->info.hz_font->sizes; index++) - { - disChar = *(lcd->info.hz_font->table + (addr)*lcd->info.hz_font->sizes + index); // 获å–ç›¸åº”çš„å­—æ¨¡åœ°å€ - - for (counter = 0; counter < 8; counter++) - { - if (disChar & 0x01) - { - pri[i] = lcd->info.color; // 当剿¨¡å€¼ä¸ä¸º0时,使用画笔色绘点 - } - else - { - pri[i] = lcd->info.back_color; // å¦åˆ™ä½¿ç”¨èƒŒæ™¯è‰²ç»˜åˆ¶ç‚¹ - } - i++; - disChar >>= 1; - Xaddress++; // æ°´å¹³åæ ‡è‡ªåŠ  - - if (Xaddress == lcd->info.hz_font->width) // å¦‚æžœæ°´å¹³åæ ‡è¾¾åˆ°äº†å­—符宽度,则退出当å‰å¾ªçޝ - { // 进入下一行的绘制 - Xaddress = 0; - break; - } - } - } - lcd->driver.set_address(lcd, x, y, x + lcd->info.hz_font->width - 1, y + lcd->info.hz_font->height - 1); // è®¾ç½®åæ ‡ - _write_buff(lcd, pri, lcd->info.hz_font->width * lcd->info.hz_font->height); // 写入显存 -} - -static void _display_text(lcd_t *lcd, uint16_t x, uint16_t y, char *text) -{ - while (*text != 0) // 判断是å¦ä¸ºç©ºå­—符 - { - if (*text <= 0x7F) // 判断是å¦ä¸ºASCIIç  - { - _display_char(lcd, x, y, *text); // 显示ASCII - x += lcd->info.ascii_font->width; // æ°´å¹³åæ ‡è°ƒåˆ°ä¸‹ä¸€ä¸ªå­—符处 - text++; // 字符串地å€+1 - } - else // 若字符为汉字 - { - _display_chinese(lcd, x, y, text); // 显示汉字 - x += lcd->info.hz_font->width; // æ°´å¹³åæ ‡è°ƒåˆ°ä¸‹ä¸€ä¸ªå­—符处 - text += 2; // 字符串地å€+2,汉字的编ç è¦2字节 - } - } -} - -// 设置背景色 -static void _full_fill(lcd_t *lcd, uint32_t color) -{ - uint16_t red_value = 0, green_value = 0, blue_value = 0; // å„个颜色通é“的值 - red_value = (uint16_t)((color & 0x00F80000) >> 8); // è½¬æ¢æˆ 16ä½ çš„RGB565颜色 - green_value = (uint16_t)((color & 0x0000FC00) >> 5); - blue_value = (uint16_t)((color & 0x000000F8) >> 3); - - lcd->info.back_color = (uint16_t)(red_value | green_value | blue_value); // 将颜色写入全局LCD傿•° + uint32_t len = (uint32_t)(x2 - x1 + 1) * (y2 - y1 + 1); + lcd->driver.set_address(lcd, x1, y1, x2, y2); + _write_buff(lcd, data, len); } static void _clear(lcd_t *lcd) @@ -331,8 +157,6 @@ static void _clear(lcd_t *lcd) static int32_t _init(lcd_t *lcd) { HAL_Delay(10); - pri = (uint16_t *)osel_mem_alloc2(1024 * sizeof(lcd)); - lcd->info.pri = (void *)pri; lcd->info.spi->gpios.cs->reset(*lcd->info.spi->gpios.cs); _write_command(lcd->info.spi, 0x36); // 显存访问控制 æŒ‡ä»¤ï¼Œç”¨äºŽè®¾ç½®è®¿é—®æ˜¾å­˜çš„æ–¹å¼ _write_data_8bit(lcd->info.spi, 0x00); // é…ç½®æˆ ä»Žä¸Šåˆ°ä¸‹ã€ä»Žå·¦åˆ°å³ï¼ŒRGBåƒç´ æ ¼å¼ @@ -416,12 +240,9 @@ static int32_t _init(lcd_t *lcd) lcd->info.spi->gpios.cs->set(*lcd->info.spi->gpios.cs); // 以下进行一些驱动的默认设置 - lcd->driver.set_dir(lcd, Direction_V); // é»˜è®¤ç«–å±æ˜¾ç¤º - lcd->driver.full_fill(lcd, LCD_BLACK); // 默认背景色为黑色 - lcd->driver.set_color(lcd, LCD_WHITE); // 默认画笔颜色为白色 - lcd->driver.clear(lcd); // 清除å±å¹• - lcd->driver.set_asscii_font(lcd, &ascii_font_24); // 默认ASCII字体 - lcd->info.show_num_mode = FILL_ZERO; // 设置å˜é‡æ˜¾ç¤ºæ¨¡å¼ï¼Œå¤šä½™ä½å¡«å……空格还是填充0 + lcd->driver.set_dir(lcd, Direction_V); // é»˜è®¤ç«–å±æ˜¾ç¤º + lcd->info.back_color = 0x0000; // 默认背景色为黑色 + lcd->driver.clear(lcd); // 清除å±å¹• return 0; } @@ -430,13 +251,9 @@ void lcd_tft_154_init(lcd_driver_t *driver) { DBG_ASSERT(driver != NULL __DBG_LINE); - driver->init = _init; // 已实现 - driver->set_dir = _set_dir; // 已实现 - driver->set_color = _set_color; // 已实现 - driver->set_address = _set_address; // 已实现 - driver->set_asscii_font = _set_asscii_font; // 已实现 - driver->set_hz_font = _set_hz_font; // 已实现 - driver->display_text = _display_text; // 已实现 - driver->clear = _clear; // 已实现 - driver->full_fill = _full_fill; // 已实现 + driver->init = _init; // 已实现 + driver->set_dir = _set_dir; // 已实现 + driver->set_address = _set_address; // 已实现 + driver->write_pixels = _write_pixels; // 已实现 + driver->clear = _clear; // 已实现 } diff --git a/User/system/lib/lcd/lcds.h b/User/system/lib/lcd/lcds.h index 8163798..e6095cd 100644 --- a/User/system/lib/lcd/lcds.h +++ b/User/system/lib/lcd/lcds.h @@ -204,20 +204,20 @@ typedef struct void (*backlight)(lcd_t *lcd, uint8_t sta); // 背光控制 void (*display_text)(lcd_t *lcd, uint16_t x, uint16_t y, char *text); // 显示字符串 void (*full_fill)(lcd_t *lcd, uint32_t color); - void (*set_address)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); // 设置显示区域 - void (*clear)(lcd_t *lcd); // æ¸…å± - void (*set_clear_flag)(lcd_t *lcd); // è®¾ç½®æ¸…å±æ ‡å¿— - void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // æ‹·è´æ¨¡æ¿ 0,æ‹·è´pri_template到priï¼›1,拷è´pri到pri_template; 其余清空 - void (*clear_ram)(lcd_t *lcd, uint16_t min_row, uint16_t max_row); // 清除显存 + void (*set_address)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); // 设置显示区域 + void (*write_pixels)(lcd_t *lcd, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *data); // 写åƒç´ ç¼“冲区 + void (*clear)(lcd_t *lcd); // æ¸…å± + void (*set_clear_flag)(lcd_t *lcd); // è®¾ç½®æ¸…å±æ ‡å¿— + void (*copy_template)(lcd_t *lcd, template_copy_type_e dir); // æ‹·è´æ¨¡æ¿ 0,æ‹·è´pri_template到priï¼›1,拷è´pri到pri_template; 其余清空 + void (*clear_ram)(lcd_t *lcd, uint16_t min_row, uint16_t max_row); // 清除显存 // æ‰©å±•æŽ¥å£ void (*set_asscii_font)(lcd_t *lcd, lcd_font *font); // 设置ASCII字体 void (*set_hz_font)(lcd_t *lcd, lcd_font *font); // 设置汉字字体 // èŽ·å–æŽ¥å£ - uint8_t (*get_dir)(lcd_t *lcd); // èŽ·å–æ‰«ææ–¹å‘ - BOOL(*get_clear_flag) - (lcd_t *lcd); // èŽ·å–æ¸…屿 ‡å¿— + uint8_t (*get_dir)(lcd_t *lcd); // èŽ·å–æ‰«ææ–¹å‘ + BOOL (*get_clear_flag)(lcd_t *lcd); // èŽ·å–æ¸…屿 ‡å¿— __IO BOOL idel; // 是å¦ç©ºé—² } lcd_driver_t; diff --git a/User/system/sgl/build.cmake b/User/system/sgl/build.cmake new file mode 100644 index 0000000..602234f --- /dev/null +++ b/User/system/sgl/build.cmake @@ -0,0 +1,28 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +include(${CMAKE_CURRENT_LIST_DIR}/core/build.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/draw/build.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/fonts/build.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/mm/build.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/widgets/build.cmake) diff --git a/User/system/sgl/core/build.cmake b/User/system/sgl/core/build.cmake new file mode 100644 index 0000000..6aa7611 --- /dev/null +++ b/User/system/sgl/core/build.cmake @@ -0,0 +1,33 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_core.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_log.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_math.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_event.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_anim.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_snprintf.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_misc.c +) diff --git a/User/system/sgl/core/lm.cfg b/User/system/sgl/core/lm.cfg new file mode 100644 index 0000000..277468b --- /dev/null +++ b/User/system/sgl/core/lm.cfg @@ -0,0 +1,31 @@ +# source/core/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +SRC += sgl_core.c +SRC += sgl_log.c +SRC += sgl_math.c +SRC += sgl_event.c +SRC += sgl_anim.c +SRC += sgl_misc.c +SRC += sgl_snprintf.c diff --git a/User/system/sgl/core/sgl_anim.c b/User/system/sgl/core/sgl_anim.c new file mode 100644 index 0000000..7775935 --- /dev/null +++ b/User/system/sgl/core/sgl_anim.c @@ -0,0 +1,422 @@ +/* source/core/sgl_anim.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + + +#if (CONFIG_SGL_ANIMATION) + +sgl_anim_ctx_t sgl_anim_ctx = { + .anim_list_head = NULL, + .anim_list_tail = NULL, +}; + + +/** + * @brief Animation static initialization + * @param anim - Animation object + * @return none + */ +void sgl_anim_init(sgl_anim_t *anim) +{ + anim->next = NULL; + anim->data = NULL; + anim->act_delay = 0; + anim->act_duration = 0; + anim->start_value = 0; + anim->end_value = 0; + + anim->path_cb = NULL; + anim->path_algo = NULL; + + anim->finish_cb = NULL; + anim->auto_free = 0; + anim->finished = 1; +} + + +/** + * @brief dynamic alloc animation object with initialization + * @param none + * @return animation object +*/ +sgl_anim_t* sgl_anim_create(void) +{ + sgl_anim_t *anim = sgl_malloc(sizeof(sgl_anim_t)); + if (anim == NULL) { + SGL_LOG_ERROR("sgl_anim_create: malloc failed"); + return NULL; + } + + sgl_anim_init(anim); + return anim; +} + + +/** + * @brief add animation object to animation list + * @param anim animation object + * @return none +*/ +static void sgl_anim_add(sgl_anim_t *anim) +{ + if (sgl_anim_ctx.anim_list_tail != NULL) { + sgl_anim_ctx.anim_list_tail->next = anim; + sgl_anim_ctx.anim_list_tail = anim; + } + else { + sgl_anim_ctx.anim_list_head = anim; + sgl_anim_ctx.anim_list_tail = anim; + } + + anim->next = NULL; + anim->finished = 0; +} + + +/** + * @brief remove animation object from animation list + * @param anim animation object + * @return none +*/ +static void sgl_anim_remove(sgl_anim_t *anim) +{ + SGL_ASSERT(anim != NULL); + sgl_anim_t *prev = NULL; + + if (sgl_anim_ctx.anim_list_head == anim) { + sgl_anim_ctx.anim_list_head = anim->next; + if (sgl_anim_ctx.anim_list_head == NULL) { + sgl_anim_ctx.anim_list_tail = NULL; + } + return; + } + + prev = sgl_anim_ctx.anim_list_head; + while (prev != NULL && prev->next != anim) { + prev = prev->next; + } + + if (prev == NULL) { + return; + } + prev->next = anim->next; + + if (anim == sgl_anim_ctx.anim_list_tail) { + sgl_anim_ctx.anim_list_tail = prev; + } +} + + +/** + * @brief start animation + * @param anim animation object + * @para repeat_cnt repeat count of animation + * @return none +*/ +void sgl_anim_start(sgl_anim_t *anim, uint32_t repeat_cnt) +{ + SGL_ASSERT(anim != NULL); + if (anim->finished && repeat_cnt) { + sgl_anim_add(anim); + anim->finished = 0; + } + + anim->act_delay = sgl_tick_get(); + anim->repeat_cnt = repeat_cnt & SGL_ANIM_REPEAT_LOOP; +} + + +/** + * @brief stop animation + * @param anim animation object + * @return none +*/ +void sgl_anim_stop(sgl_anim_t *anim) +{ + SGL_ASSERT(anim != NULL); + if (!anim->finished) { + sgl_anim_remove(anim); + anim->finished = 1; + } + anim->act_delay = 0; +} + + +/** + * @brief delete animation object + * @param anim animation object + * @return none +*/ +void sgl_anim_delete(sgl_anim_t *anim) +{ + SGL_ASSERT(anim != NULL); + if (!anim->finished) { + sgl_anim_stop(anim); + } + sgl_free(anim); +} + + +/** + * @brief animation task, it will foreach all animation + * @param none + * @return none + * @note this function should be called in sgl_task() + */ +void sgl_anim_task(void) +{ + int32_t value = 0; + uint32_t elaps_time = 0, act_time = 0; + sgl_anim_t *anim = sgl_anim_ctx.anim_list_head, *next = NULL; + + while (anim != NULL) { + act_time = sgl_tick_get(); + + if(act_time < anim->act_delay) { + continue; + } + + elaps_time = act_time - anim->act_delay; + + /* check callback function for debug */ + SGL_ASSERT(anim->path_cb != NULL); + SGL_ASSERT(anim->path_algo != NULL); + value = anim->path_algo(sgl_min(elaps_time, anim->act_duration), anim->act_duration, anim->start_value, anim->end_value); + anim->path_cb(anim, value); + + if (elaps_time > anim->act_duration) { + if (anim->repeat_cnt != SGL_ANIM_REPEAT_LOOP) { + anim->repeat_cnt--; + } + + if (anim->finish_cb) { + anim->finish_cb(anim); + } + + /* remove anim object if repeat count is 0 */ + if (anim->repeat_cnt == 0) { + sgl_anim_stop(anim); + + /* if animation is auto free, free it */ + if (anim->auto_free) { + next = anim->next; + sgl_free(anim); + anim = next; + continue; + } + } + + anim->act_delay += anim->act_duration; + } + + anim = anim->next; + } +} + + +/** + * Linear animation path calculation function + * + * Calculates the current interpolated value based on elapsed time and total duration + * using linear interpolation. + * + * @param elaps Elapsed time in milliseconds + * @param duration Total animation duration in milliseconds + * @param start Start value + * @param end End value + * + * @return The interpolated value for the current time + * + * @note Returns 'end' if elaps >= duration (animation finished) + * Returns 'start' if elaps == 0 (animation just started) + * Uses 32-bit integer arithmetic to avoid floating-point operations + * for better performance on embedded systems + */ +int32_t sgl_anim_path_linear(uint32_t elaps, uint32_t duration, int32_t start, int32_t end) +{ + int64_t progress_fixed, delta, result; + + // If duration is zero or elapsed time exceeds duration, return end value + if (duration == 0 || elaps >= duration) { + return (int32_t)end; + } + + // If no time has elapsed, return start value + if (elaps == 0) { + return (int32_t)start; + } + + // Calculate progress (elaps / duration) as a fixed-point number with 16 fractional bits + // Use 64-bit intermediate to prevent overflow during multiplication + progress_fixed = ((int64_t)elaps << 16) / duration; + + // Calculate the difference between end and start + delta = end - start; + + // Compute the interpolated result: start + delta * (elaps/duration) + // Right-shift by 16 to scale back from fixed-point representation + result = start + ((delta * progress_fixed) >> 16); + + return result; +} + + +/** + * sgl_anim_path_ease_in_out - Cubic ease-in-out animation path + * + * This function creates a smooth animation curve that starts slow, + * accelerates in the middle, and decelerates at the end. + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_in_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end) +{ + int32_t t_180, cos_val, delta; + if (elaps >= duration) + return end; + if (elaps == 0) + return start; + + t_180 = (elaps * 180) / duration; + + if (t_180 <= 90) { + cos_val = sgl_sin(90 - t_180); + } else { + cos_val = -sgl_sin(t_180 - 90); + } + + // Now: progress = 0.5 * (1 - cos_val/1000) = (1000 - cos_val) / 2000 + // So: result = start + (end - start) * (1000 - cos_val) / 2000 + delta = end - start; + return start + (delta * (32767 - cos_val)) / 65535; +} + + +/** + * sgl_anim_path_ease_out - Cubic ease-in animation path + * + * This function creates a smooth animation curve that starts accelerates, + * it will be slow in the after + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end) +{ + int32_t angle, sin_val, delta; + if (elaps >= duration) + return end; + if (elaps == 0) + return start; + + // t ∈ [0, 90] degrees: sin(t * 90 / duration) + angle = (elaps * 90) / duration; + sin_val = sgl_sin(angle); // Assume returns 0 ~ 65535 or Q15 + + // If sgl_sin returns ×1000 (e.g., sin(90) = 32767) + delta = end - start; + return start + ((delta * sin_val) >> 15); +} + + +/** + * sgl_anim_path_ease_in - Cubic ease-in animation path + * + * This function creates a smooth animation curve that starts accelerates, + * accelerates in the after + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_in(uint32_t elaps, uint32_t duration, int32_t start, int32_t end) +{ + int32_t angle, cos_val, delta; + if (elaps >= duration) + return end; + if (elaps == 0) + return start; + + // t ∈ [0, 90] degrees: sin(t * 90 / duration) + angle = (elaps * 90) / duration; + cos_val = sgl_cos(angle); // Assume returns 0 ~ 65535 or Q15 + + // If sgl_sin returns ×1000 (e.g., sin(90) = 32767) + delta = end - start; + return start + ((delta * (32767 - cos_val)) >> 15); +} + + +/** + * sgl_anim_path_overshoot - Overshoot animation path + * + * This function creates an animation curve that overshoots the target end value + * slightly before settling back to it, creating a natural "bounce" or "spring-like" + * effect for a more dynamic and realistic animation. + * + * @param elaps Elapsed time (ms) since the animation started + * @param duration Total animation duration (ms) + * @param start Initial value of the animated property at the start of the animation + * @param end Target end value of the animated property + * @return Interpolated value of the animated property at the current elapsed time + */ +int32_t sgl_anim_path_overshoot(uint32_t elaps, uint32_t duration, int32_t start, int32_t end) +{ + int64_t t, t1, t2, inv_t2, ease_back, diff, progress; + if (elaps >= duration) + return end; + + t = (int64_t)elaps * 16384 / duration; + diff = end - start; + + if (t < 11468) { + t1 = t * 16384 / 11468; + progress = (t1 * (32768 - t1)) >> 14; + progress = (progress * 18841) >> 14; + } + else { + t2 = (t - 11468) * 16384 / (16384 - 11468); + inv_t2 = 16384 - t2; + ease_back = (inv_t2 * inv_t2) >> 14; + progress = 16384 + (ease_back * (18841 - 16384) >> 14); + } + + return start + (int32_t)((diff * progress) >> 14); +} + +#endif // !CONFIG_SGL_ANIMATION diff --git a/User/system/sgl/core/sgl_core.c b/User/system/sgl/core/sgl_core.c new file mode 100644 index 0000000..5b28866 --- /dev/null +++ b/User/system/sgl/core/sgl_core.c @@ -0,0 +1,1611 @@ +/* source/core/sgl_core.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* current sgl system variable, do not used it */ +sgl_system_t sgl_system; + + +/** + * @brief Alpha blending table for 4 bpp and 2 bpp + */ +const uint8_t sgl_opa4_table[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255 }; +const uint8_t sgl_opa2_table[4] = {0, 85, 170, 255}; + + +/** + * the memory pool, it will be used to allocate memory for the page pool +*/ +static uint8_t sgl_mem_pool[CONFIG_SGL_HEAP_MEMORY_SIZE]; + + +/** + * @brief register the frame buffer device + * @param fbinfo the frame buffer device information + * @return int, 0 if success, -1 if failed + * @note you must check the result of this function + */ +int sgl_fbdev_register(sgl_fbinfo_t *fbinfo) +{ + sgl_check_ptr_return(fbinfo, -1); + + if (fbinfo->buffer[0] == NULL) { + SGL_LOG_ERROR("You haven't set up the frame buffer."); + SGL_ASSERT(0); + return -1; + } + + if (fbinfo->flush_area == NULL) { + SGL_LOG_ERROR("You haven't set up the flush area."); + SGL_ASSERT(0); + return -1; + } + + if (fbinfo->buffer_size == 0) { + SGL_LOG_ERROR("You haven't set up the frame buffer size."); + SGL_ASSERT(0); + return -1; + } + + sgl_system.fbdev.fbinfo = *fbinfo; + + sgl_system.fbdev.surf.buffer = (sgl_color_t*)fbinfo->buffer[0]; + sgl_system.fbdev.surf.x1 = 0; + sgl_system.fbdev.surf.y1 = 0; + sgl_system.fbdev.surf.x2 = fbinfo->xres - 1; + sgl_system.fbdev.surf.y2 = fbinfo->yres - 1; + sgl_system.fbdev.surf.size = fbinfo->buffer_size; + sgl_system.fbdev.surf.w = fbinfo->xres; + + sgl_system.tick_ms = 0; + sgl_system.fbdev.fb_status = 3; + sgl_system.fbdev.fb_swap = 0; + + return 0; +} + + +/** + * @brief get pixmap bytes of per pixel + * @param pixmap pointer to pixmap + * @return pixmap bytes of per pixel + */ +uint8_t sgl_pixmal_get_bytes_per_pixel(const sgl_pixmap_t *pixmap) +{ + static const uint8_t s_bytes_per_pixel[] = { + [SGL_PIXMAP_FMT_NONE] = sizeof(sgl_color_t), + [SGL_PIXMAP_FMT_RGB332] = 1, + [SGL_PIXMAP_FMT_ARGB2222] = 1, + [SGL_PIXMAP_FMT_RLE_RGB332] = 1, + [SGL_PIXMAP_FMT_RLE_ARGB2222] = 1, + [SGL_PIXMAP_FMT_RGB565] = 2, + [SGL_PIXMAP_FMT_ARGB4444] = 2, + [SGL_PIXMAP_FMT_RLE_RGB565] = 2, + [SGL_PIXMAP_FMT_RLE_ARGB4444] = 2, + [SGL_PIXMAP_FMT_RGB888] = 3, + [SGL_PIXMAP_FMT_RLE_RGB888] = 3, + [SGL_PIXMAP_FMT_ARGB8888] = 4, + [SGL_PIXMAP_FMT_RLE_ARGB8888] = 4, + }; + + SGL_ASSERT(pixmap != NULL); + if (pixmap->format >= sizeof(s_bytes_per_pixel)) { + SGL_LOG_ERROR("pixmap format error"); + return 0; + } + return s_bytes_per_pixel[pixmap->format]; +} + + +/** + * @brief add object to parent + * @param parent: pointer of parent object + * @param obj: pointer of object + * @return none + */ +void sgl_obj_add_child(sgl_obj_t *parent, sgl_obj_t *obj) +{ + SGL_ASSERT(parent != NULL && obj != NULL); + sgl_obj_t *tail = parent->child; + + if (parent->child) { + while (tail->sibling != NULL) { + tail = tail->sibling; + }; + tail->sibling = obj; + } + else { + parent->child = obj; + } + + obj->parent = parent; +} + + +/** + * @brief remove an object from its parent + * @param obj object to remove + * @return none + * @note This function will remove the object from its parent, of course, his children will also be removed + */ +void sgl_obj_remove(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + + sgl_obj_t *parent = obj->parent; + sgl_obj_t *pos = NULL; + + if (parent->child != obj) { + pos = parent->child; + while (pos->sibling != obj) { + pos = pos->sibling; + } + pos->sibling = obj->sibling; + } + else { + parent->child = obj->sibling; + } + + obj->sibling = NULL; +} + + +/** + * @brief move object child position + * @param obj point to object + * @param ofs_x: x offset position + * @param ofs_y: y offset position + * @return none + */ +void sgl_obj_move_child_pos(sgl_obj_t *obj, int16_t ofs_x, int16_t ofs_y) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + int top = 0; + + if (obj->child == NULL) { + return; + } + stack[top++] = obj->child; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + + obj->dirty = 1; + obj->coords.x1 += ofs_x; + obj->coords.x2 += ofs_x; + obj->coords.y1 += ofs_y; + obj->coords.y2 += ofs_y; + + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + } +} + + +/** + * @brief Set object absolute position + * @param obj point to object + * @param abs_x: x absolute position + * @param abs_y: y absolute position + * @return none + */ +void sgl_obj_set_abs_pos(sgl_obj_t *obj, int16_t abs_x, int16_t abs_y) +{ + SGL_ASSERT(obj != NULL); + int16_t x_diff = abs_x - obj->coords.x1; + int16_t y_diff = abs_y - obj->coords.y1; + + obj->dirty = 1; + obj->coords.x1 += x_diff; + obj->coords.x2 += x_diff; + obj->coords.y1 += y_diff; + obj->coords.y2 += y_diff; + + sgl_obj_move_child_pos(obj, x_diff, y_diff); +} + + +/** + * @brief zoom object size + * @param obj point to object + * @param zoom zoom size + * @return none + * @note if you want to zoom out, the zoom should be positive, if you want to zoom in, the zoom should be negative + */ +void sgl_obj_size_zoom(sgl_obj_t *obj, int16_t zoom) +{ + SGL_ASSERT(obj != NULL); + obj->coords.x1 -= zoom; + obj->coords.x2 += zoom; + obj->coords.y1 -= zoom; + obj->coords.y2 += zoom; +} + + +/** + * @brief move object up a level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_up(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *parent = obj->parent; + sgl_obj_t *prev = NULL; + sgl_obj_t *next = NULL; + + /* if the object is the last child, do not move it */ + if (obj->sibling == NULL) { + return; + } + else if (parent->child == obj) { + parent->child = obj->sibling; + obj->sibling = obj->sibling->sibling; + /* mark object as dirty */ + sgl_obj_set_dirty(obj); + return; + } + + /* move the object to its next sibling */ + sgl_obj_for_each_child(prev, parent) { + if (prev->sibling == obj) { + next = obj->sibling; + obj->sibling = next->sibling; + prev->sibling = next; + next->sibling = obj; + /* mark object as dirty */ + sgl_obj_set_dirty(obj); + return; + } + } +} + + +/** + * @brief move object down a level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_down(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *parent = obj->parent; + sgl_obj_t *prev_prev = NULL; + sgl_obj_t *prev = NULL; + + if (parent->child == obj) { + return; + } + + // Find the previous sibling node (prev) and the node before it (prev_prev) + sgl_obj_for_each_child(prev, parent) { + if (prev->sibling == obj) { + break; + } + prev_prev = prev; + } + + if (prev != NULL) { + if (prev_prev != NULL) { + prev_prev->sibling = obj; + } + else { + parent->child = obj; + } + + prev->sibling = obj->sibling; + obj->sibling = prev; + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief move object top level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_top(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL && obj->parent != NULL); + + sgl_obj_t *parent = obj->parent; + sgl_obj_t *prev = NULL, *curr = parent->child, *last = NULL; + + /* if the object is the last child, do not move it */ + if (obj->sibling == NULL) { + return; + } + + while (curr != NULL && curr != obj) { + prev = curr; + curr = curr->sibling; + } + + if (prev == NULL) { + parent->child = obj->sibling; + } + else { + prev->sibling = obj->sibling; + } + + last = parent->child; + if (last == NULL) { + parent->child = obj; + obj->sibling = NULL; + } + else { + while (last->sibling != NULL) { + last = last->sibling; + } + last->sibling = obj; + obj->sibling = NULL; + } + + sgl_obj_set_dirty(obj); +} + + +/** + * @brief move object bottom level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_bottom(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *parent = obj->parent; + sgl_obj_t *prev = NULL; + + /* if the object is the first child, do not move it */ + if (parent->child == obj) { + return; + } + + sgl_obj_for_each_child(prev, parent) { + if (prev->sibling == obj) { + break; + } + } + + prev->sibling = obj->sibling; + obj->sibling = parent->child; + parent->child = obj; + /* mark object as dirty */ + sgl_obj_set_dirty(obj); +} + + +/** + * @brief get fix radius of object + * @param obj object + * @param radius: radius that you want to set + * @return none + * @note if radius is larger than object's width or height, fix radius will be returned + */ +void sgl_obj_set_radius(sgl_obj_t *obj, size_t radius) +{ + int16_t w = (obj->coords.x2 - obj->coords.x1 + 1); + int16_t h = (obj->coords.y2 - obj->coords.y1 + 1); + int16_t d_min = w > h ? h : w; + + if ((int16_t)radius >= (d_min / 2)) { + radius = sgl_is_odd(d_min) ? d_min / 2 : (d_min - 1) / 2; + } + + obj->radius = radius & 0xFFF; +} + + +#if (CONFIG_SGL_OBJ_USE_NAME && CONFIG_SGL_DEBUG) +/** + * @brief print object name that include this all child + * @param obj point to object + * @return none + */ +void sgl_obj_print_name(sgl_obj_t *obj) +{ + int top = 0; + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + stack[top++] = obj; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + + if (obj->name == NULL) { + SGL_LOG_INFO("[OBJ NAME]: %s", "NULL"); + } + else { + SGL_LOG_INFO("[OBJ NAME]: %s", obj->name); + } + + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + } +} + +#endif + + +/** + * @brief page construct callback function + * @param surf surface pointer + * @param obj page object + * @param evt event + * @return none + * @note evt not used + */ +static void sgl_page_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_page_t *page = (sgl_page_t *)obj; + const sgl_pixmap_t *pixmap = page->pixmap; + + if (evt->type == SGL_EVENT_DRAW_MAIN) { + if (pixmap == NULL) { + sgl_draw_fill_rect(surf, &obj->area, &obj->coords, 0, page->color, page->alpha); + } + else { + sgl_draw_fill_rect_pixmap(surf, &obj->area, &obj->coords, 0, pixmap, page->alpha); + } + } + else { + if (obj->event_fn) { + obj->event_fn(evt); + } + } +} + + +/** + * @brief set page background color + * @param obj point to object + * @param color background color + * @return none + */ +void sgl_page_set_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_page_t* page = (sgl_page_t*)obj; + page->color = color; + sgl_obj_set_dirty(obj); +} + + +/** + * @brief set page background pixmap + * @param obj point to object + * @param pixmap background pixmap + * @return none + */ +void sgl_page_set_pixmap(sgl_obj_t* obj, const sgl_pixmap_t *pixmap) +{ + sgl_page_t* page = (sgl_page_t*)obj; + page->pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + + +/** + * @brief set page background alpha + * @param obj point to object + * @param alpha background alpha + * @return none + */ +void sgl_page_set_alpha(sgl_obj_t* obj, uint8_t alpha) +{ + sgl_page_t* page = (sgl_page_t*)obj; + page->alpha = alpha; + sgl_obj_set_dirty(obj); +} + + +/** + * @brief create a page + * @param none + * @return sgl_page_t* the page pointer + */ +static sgl_page_t* sgl_page_create(void) +{ + sgl_page_t *page = sgl_malloc(sizeof(sgl_page_t)); + if (page == NULL) { + SGL_LOG_ERROR("sgl_page_create: malloc failed"); + return NULL; + } + + /* clear the page all fields */ + memset(page, 0, sizeof(sgl_page_t)); + + sgl_obj_t *obj = &page->obj; + + if (sgl_system.fbdev.fbinfo.buffer[0] == NULL) { + SGL_LOG_ERROR("sgl_page_create: framebuffer is NULL"); + sgl_free(page); + return NULL; + } + + page->color = SGL_THEME_DESKTOP; + page->alpha = SGL_ALPHA_MAX; + + obj->parent = obj; + obj->clickable = 0; + obj->construct_fn = sgl_page_construct_cb; + obj->dirty = 1; + obj->page = 1; + obj->border = 0; + obj->coords = (sgl_area_t) { + .x1 = 0, + .y1 = 0, + .x2 = sgl_system.fbdev.fbinfo.xres - 1, + .y2 = sgl_system.fbdev.fbinfo.yres - 1, + }; + + obj->area = obj->coords; + + /* init child list */ + sgl_obj_node_init(&page->obj); + + if (sgl_system.fbdev.active == NULL) { + sgl_system.fbdev.active = &page->obj; + } + + return page; +} + + +/** + * @brief Create an object + * @param parent parent object + * @return sgl_obj_t + * @note if parent is NULL, the object will be as an new page + */ +sgl_obj_t* sgl_obj_create(sgl_obj_t *parent) +{ + sgl_obj_t *obj; + + /* create page object */ + if (parent == NULL) { + sgl_page_t *page = sgl_page_create(); + if (page == NULL) { + SGL_LOG_ERROR("sgl_obj_create: create page failed"); + return NULL; + } + obj = &page->obj; + return obj; + } + else { + obj = (sgl_obj_t*)sgl_malloc(sizeof(sgl_obj_t)); + if (obj == NULL) { + SGL_LOG_ERROR("malloc failed"); + return NULL; + } + + obj->coords = parent->coords; + obj->parent = parent; + obj->event_fn = NULL; + obj->event_data = 0; + obj->construct_fn = NULL; + obj->dirty = 1; + + /* init node */ + sgl_obj_node_init(obj); + /* add the child into parent's child list */ + sgl_obj_add_child(parent, obj); + + return obj; + } +} + + +/** + * @brief initialize global dirty area + * @param none + * @return none + */ +static inline void sgl_dirty_area_init(void) +{ + sgl_system.fbdev.dirty_num = 0; +} + + +/** + * @brief sgl global initialization + * @param none + * @return int, 0 means success, others means failed + * @note you should call this function before using sgl and you should call this function after register framebuffer device + */ +int sgl_init(void) +{ + sgl_obj_t *obj = NULL; + + /* init memory pool */ + sgl_mm_init(sgl_mem_pool, sizeof(sgl_mem_pool)); + + /* initialize current context */ + sgl_system.fbdev.active = NULL; + + /* initialize dirty area */ + sgl_dirty_area_init(); + + /* create a screen object for drawing */ + obj = sgl_obj_create(NULL); + if (obj == NULL) { + SGL_LOG_ERROR("sgl_init: create screen object failed"); + return -1; + } + + /* if the rotation is not 0 or 180, we need to alloc a buffer for rotation */ +#if ((CONFIG_SGL_FBDEV_ROTATION != 0) || CONFIG_SGL_FBDEV_RUNTIME_ROTATION) + sgl_system.rotation = (sgl_color_t*)sgl_malloc(sgl_system.fbdev.fbinfo.buffer_size * sizeof(sgl_color_t)); + if (sgl_system.rotation == NULL) { + SGL_LOG_ERROR("sgl_init: alloc rotation buffer failed"); + return -1; + } +#if (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) + sgl_system.angle = 0; +#endif +#endif + /* create event queue */ + if (sgl_event_queue_init()) { + SGL_LOG_ERROR("sgl_init: event queue init failed"); + sgl_free(obj); + return -1; + } + +#if (CONFIG_SGL_BOOT_LOGO) + sgl_boot_logo(); +#endif + return 0; +} + + +/** + * @brief set current object as screen object + * @param obj object, that you want to set an object as active page + * @return none + */ +void sgl_screen_load(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_system.fbdev.active = obj; + + /* initialize dirty area */ + sgl_dirty_area_init(); + sgl_obj_set_dirty(obj); +} + + +#if (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) +/** + * @brief set framebuffer device rotation angle + * @param angle [in] rotation angle, that is 0, 90, 180, 270 + * @return none + * @note Rotation angle must be 0, 90, 180, 270 + */ +void sgl_fbdev_set_angle(uint16_t angle) +{ + if (angle == sgl_system.angle) { + return; + } + + const uint8_t cur_status = (sgl_system.angle == 0 || sgl_system.angle == 180) ? 0 : + (sgl_system.angle == 90 || sgl_system.angle == 270) ? 1 : 2; + + const uint8_t new_status = (angle == 0 || angle == 180) ? 0 : + (angle == 90 || angle == 270) ? 1 : 2; + + if (cur_status == 2 || new_status == 2) { + SGL_LOG_WARN("sgl_fbdev_set_angle: invalid angle"); + return; + } + + if (cur_status != new_status) { + sgl_swap(&sgl_system.fbdev.fbinfo.xres, &sgl_system.fbdev.fbinfo.yres); + } + + sgl_system.angle = angle; + sgl_obj_set_dirty(sgl_system.fbdev.active); +} +#endif // !CONFIG_SGL_FBDEV_RUNTIME_ROTATION + + +/** + * @brief Get area intersection between two areas + * @param area_a: area a + * @param area_b: area b + * @param clip: intersection area + * @return true: intersect, otherwise false + * @note: this function is unsafe, you should check the area_a and area_b and clip is not NULL by yourself + */ +bool sgl_area_clip(sgl_area_t *area_a, sgl_area_t *area_b, sgl_area_t *clip) +{ + SGL_ASSERT(area_a != NULL && area_b != NULL && clip != NULL); + if (area_b->y1 > area_a->y2 || area_b->y2 < area_a->y1 || area_b->x1 > area_a->x2 || area_b->x2 < area_a->x1) { + return false; + } + + clip->x1 = sgl_max(area_a->x1, area_b->x1); + clip->x2 = sgl_min(area_a->x2, area_b->x2); + clip->y1 = sgl_max(area_a->y1, area_b->y1); + clip->y2 = sgl_min(area_a->y2, area_b->y2); + + return true; +} + + +/** + * @brief clip area with another area + * @param clip [in][out] clip area + * @param area [in] area + * @return true if clip area is valid, otherwise two area is not overlapped + * @note: this function is unsafe, you should check the clip and area is not NULL by yourself + */ +bool sgl_area_selfclip(sgl_area_t *clip, sgl_area_t *area) +{ + SGL_ASSERT(clip != NULL && area != NULL); + if (area->y1 > clip->y2 || area->y2 < clip->y1 || area->x1 > clip->x2 || area->x2 < clip->x1) { + return false; + } + + clip->x1 = sgl_max(clip->x1, area->x1); + clip->x2 = sgl_min(clip->x2, area->x2); + clip->y1 = sgl_max(clip->y1, area->y1); + clip->y2 = sgl_min(clip->y2, area->y2); + + return true; +} + + +/** + * @brief Computes the total boundary expansion (in Manhattan distance) required to merge rectangle b into rectangle a. + * + * @param a[in] Pointer to the b rectangle + * @param b[in] Pointer to the a rectangle + * @return int32_t Total expansion amount (always non-negative) + */ +static inline int32_t sgl_area_growth(sgl_area_t *a, sgl_area_t *b) +{ + return (a->x1 - sgl_min(a->x1, b->x1)) + (sgl_max(a->x2, b->x2) - a->x2) + + (a->y1 - sgl_min(a->y1, b->y1)) + (sgl_max(a->y2, b->y2) - a->y2); +} + + +/** + * @brief Quickly determines if two rectangles are close enough to be merged. + * + * This fast heuristic is useful in performance-critical contexts (e.g., real-time segmentation or region merging) + * to avoid excessive fragmentation while preventing merges between distant regions. + * + * @param a[in] Pointer to the first rectangle + * @param b[in] Pointer to the second rectangle + * @return bool true if the rectangles are sufficiently close for merging; false otherwise + */ +static inline bool sgl_merge_determines(sgl_area_t* a, sgl_area_t* b) +{ + int16_t gap_x = (a->x1 > b->x2) ? (a->x1 - b->x2) : (b->x1 > a->x2) ? (b->x1 - a->x2) : 0; + int16_t gap_y = (a->y1 > b->y2) ? (a->y1 - b->y2) : (b->y1 > a->y2) ? (b->y1 - a->y2) : 0; + int16_t threshold = (sgl_min4(a->x2 - a->x1 + 1, a->y2 - a->y1 + 1, b->x2 - b->x1 + 1, b->y2 - b->y1 + 1) >> 2); + + return (gap_x <= threshold) && (gap_y <= threshold); +} + + +/** + * @brief merge an area into global dirty area + * + * This function calculates how much rectangle 'a' would need to grow in each direction (left, right, top, bottom) + * to fully enclose both 'a' and 'b'. The result is the sum of the expansions along all four sides. + * Note: This is not the increase in area, th is a lightweight heuristic for merge cost in bounding-box algorithms. + * + * @param area [in] Pointer to the area + * @return none + */ +void sgl_dirty_area_push(sgl_area_t *area) +{ + SGL_ASSERT(area != NULL); + int32_t best_idx = -1, min_growth = INT32_MAX, growth = INT32_MAX; + /* skip invalid area */ + if (area->x1 > area->x2 || area->y1 > area->y2) { + return; + } + + if (sgl_system.fbdev.dirty_num == 0) { + sgl_system.fbdev.dirty[0] = *area; + sgl_system.fbdev.dirty_num = 1; + return; + } + + for (uint8_t i = 0; i < sgl_system.fbdev.dirty_num; i++) { + if (sgl_merge_determines(&sgl_system.fbdev.dirty[i], area)) { + growth = sgl_area_growth(&sgl_system.fbdev.dirty[i], area); + if (growth == 0) { + /* already contains the area */ + return; + } + else if (growth < min_growth) { + min_growth = growth; + best_idx = i; + } + } + } + + if (best_idx >= 0) { + /* merge object area into best_idx dirty area */ + sgl_area_selfmerge(&sgl_system.fbdev.dirty[best_idx], area); + return; + } + + if (sgl_system.fbdev.dirty_num < SGL_DIRTY_AREA_NUM_MAX) { + /* add new dirty area */ + sgl_system.fbdev.dirty[sgl_system.fbdev.dirty_num++] = *area; + } else { + /* merge object area into last dirty area */ + sgl_area_selfmerge(&sgl_system.fbdev.dirty[SGL_DIRTY_AREA_NUM_MAX - 1], area); + } +} + + +/** + * @brief initialize object + * @param obj object + * @param parent parent object + * @return int, 0 means successful, -1 means failed + */ +int sgl_obj_init(sgl_obj_t *obj, sgl_obj_t *parent) +{ + SGL_ASSERT(obj != NULL); + + if (parent == NULL) { + parent = sgl_screen_act(); + if (parent == NULL) { + SGL_LOG_ERROR("sgl_obj_init: have no active page"); + return -1; + } + } + + /* set essential member */ + obj->coords = parent->coords; + obj->parent = parent; + obj->event_fn = NULL; + obj->event_data = 0; + obj->construct_fn = NULL; + obj->dirty = 1; + obj->clickable = 0; + + /* init object area to invalid */ + sgl_area_init(&obj->area); + + /* add the child into parent's child list */ + sgl_obj_add_child(parent, obj); + + return 0; +} + + +/** + * @brief free an object + * @param obj: object to free + * @retval none + * @note this function will free all the itself and children of the object + */ +void sgl_obj_free(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + int top = 0; + stack[top++] = obj; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + + sgl_free(obj); + } +} + + +/** + * @brief Clear all dirty areas of the object and its children. + * @param[in] obj The object to clear. + * @return None + * @note This function is used to clear all dirty areas of the object and its children. + */ +void sgl_obj_clear_all_dirty(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + int top = 0; + stack[top++] = obj; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + obj->dirty = 0; + + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + } +} + + +/** + * @brief delete object + * @param obj point to object + * @return none + * @note this function will set object and his childs to be destroyed, then next draw cycle, the object will be removed. + * if object is NULL, the all objects of active page will be delete, but the page object will not be deleted. + * if object is a page, the page object will be deleted and all its children will be deleted. + */ +void sgl_obj_delete(sgl_obj_t *obj) +{ + if (obj == NULL || obj == sgl_screen_act()) { + obj = sgl_screen_act(); + if (obj->child) { + sgl_obj_free(obj->child); + } + sgl_obj_node_init(obj); + sgl_obj_set_dirty(obj); + return; + } + else if (obj->page == 1) { + sgl_obj_free(obj); + return; + } + + sgl_obj_set_destroyed(obj); +} + + +/** + * @brief Convert UTF-8 string to Unicode + * @param utf8_str Pointer to the UTF-8 string to be converted + * @param p_unicode_buffer Pointer to the buffer where the converted Unicode will be stored + * @return The number of bytes in the UTF-8 string + */ +uint32_t sgl_utf8_to_unicode(const char *utf8_str, uint32_t *p_unicode_buffer) +{ + uint8_t* ptr = (uint8_t*)utf8_str; + if ((*ptr) < 0x80) { // 1-byte/7-bit ASCII + *p_unicode_buffer = ptr[0]; + return 1; + } + else if (((*ptr) & 0xE0) == 0xC0) { // 2-byte + *p_unicode_buffer = (ptr[0] & 0x1F) << 6 | (ptr[1] & 0x3F); + return 2; + } + else if (((*ptr) & 0xF0) == 0xE0) { // 3-byte + *p_unicode_buffer = (ptr[0] & 0x0F) << 12 | (ptr[1] & 0x3F) << 6 | (ptr[2] & 0x3F); + return 3; + } + else if (((*ptr) & 0xF8) == 0xF0) { // 4-byte + *p_unicode_buffer = (ptr[0] & 0x07) << 18 | (ptr[1] & 0x3F) << 12 | (ptr[2] & 0x3F) << 6 | (ptr[3] & 0x3F); + return 4; + } + return 0; +} + + +/** + * @brief Search for the index of a Unicode character in the font table + * @param font Pointer to the font structure containing character data + * @param unicode Unicode of the character to be searched + * @return Index of the character in the font table + */ +uint32_t sgl_search_unicode_ch_index(const sgl_font_t *font, uint32_t unicode) +{ + uint32_t left = 0, right = 0, mid = 0; + uint32_t target = unicode; + const sgl_font_unicode_t *code = font->unicode; + + for (uint32_t i = 1; i < font->unicode_num; i ++) { + if (target < (code->offset + code->len)) { + break; + } + code ++; + } + + target -= code->offset; + + if (code->list == NULL) { + if (target >= code->len) { + SGL_LOG_WARN("sgl_search_unicode_ch_index: [0x%x]unicode not found in font table", unicode); + return 0; + } + return target + code->tab_offset; + } + + right = code->len - 1; + while (left <= right) { + mid = left + (right - left) / 2; + + if (code->list[mid] == target) { + return mid + code->tab_offset; + } + else if (code->list[mid] < target) { + left = mid + 1; + } + else { + right = mid - 1; + } + } + + SGL_LOG_WARN("sgl_search_unicode_ch_index: [0x%x]unicode not found in font table", unicode); + return 0; +} + + +/** + * @brief get the width of a string + * @param str string + * @param font sgl font + * @return width of string + */ +int32_t sgl_font_get_string_width(const char *str, const sgl_font_t *font) +{ + SGL_ASSERT(font != NULL); + int32_t len = 0; + uint32_t unicode = 0; + uint32_t ch_index = 0; + while (*str) { + str += sgl_utf8_to_unicode(str, &unicode); + ch_index = sgl_search_unicode_ch_index(font, unicode); + len += (font->table[ch_index].adv_w >> 4); + } + return len; +} + + +/** + * @brief get the height of a string, which is in a rect area + * @param width width of the rect area + * @param str string + * @param font sgl font of the string + * @param line_space peer line space + * @return height size of string + */ +int32_t sgl_font_get_string_height(int16_t width, const char *str, const sgl_font_t *font, uint8_t line_space) +{ + int16_t offset_x = 0; + int16_t ch_index; + int16_t ch_width; + int16_t lines = 1; + uint32_t unicode = 0; + + while (*str) { + if (*str == '\n') { + lines ++; + offset_x = 0; + str ++; + continue; + } + + str += sgl_utf8_to_unicode(str, &unicode); + ch_index = sgl_search_unicode_ch_index(font, unicode); + + ch_width = (font->table[ch_index].adv_w >> 4); + + if ((offset_x + ch_width) >= width) { + offset_x = 0; + lines ++; + } + + offset_x += ch_width; + } + + return lines * (font->font_height + line_space); +} + + +/** + * @brief get the alignment position + * @param parent_size parent size + * @param size object size + * @param type alignment type + * @return alignment position offset + */ +sgl_pos_t sgl_get_align_pos(sgl_size_t *parent_size, sgl_size_t *size, sgl_align_type_t type) +{ + SGL_ASSERT(parent_size != NULL && size != NULL); + sgl_pos_t ret = {.x = 0, .y = 0}; + + switch (type) { + case SGL_ALIGN_CENTER: + ret.x = (parent_size->w - size->w) / 2; + ret.y = (parent_size->h - size->h) / 2; + break; + + case SGL_ALIGN_TOP_MID: + ret.x = (parent_size->w - size->w) / 2; + ret.y = 0; + break; + + case SGL_ALIGN_TOP_LEFT: + ret.x = 0; + ret.y = 0; + break; + + case SGL_ALIGN_TOP_RIGHT: + ret.x = parent_size->w - size->w; + ret.y = 0; + break; + + case SGL_ALIGN_BOT_MID: + ret.x = (parent_size->w - size->w) / 2; + ret.y = parent_size->h - size->h; + break; + + case SGL_ALIGN_BOT_LEFT: + ret.x = 0; + ret.y = parent_size->h - size->h; + break; + + case SGL_ALIGN_BOT_RIGHT: + ret.x = parent_size->w - size->w; + ret.y = parent_size->h - size->h; + break; + + case SGL_ALIGN_LEFT_MID: + ret.x = 0; + ret.y = (parent_size->h - size->h) / 2; + break; + + case SGL_ALIGN_RIGHT_MID: + ret.x = parent_size->w - size->w; + ret.y = (parent_size->h - size->h) / 2; + break; + + default: break; + } + return ret; +} + + +/** + * @brief get the text position in the area + * @param area point to area + * @param font point to font + * @param text text string + * @param offset text offset + * @param type alignment type + * @return sgl_pos_t position of text + */ +sgl_pos_t sgl_get_text_pos(sgl_area_t *area, const sgl_font_t *font, const char *text, int16_t offset, sgl_align_type_t type) +{ + SGL_ASSERT(area != NULL && font != NULL); + sgl_pos_t ret = {.x = 0, .y = 0}; + sgl_size_t parent_size = { + .w = area->x2 - area->x1 + 1, + .h = area->y2 - area->y1 + 1, + }; + + sgl_size_t text_size = { + .w = sgl_font_get_string_width(text, font) + offset, + .h = sgl_font_get_height(font), + }; + + ret = sgl_get_align_pos(&parent_size, &text_size, type); + ret.x += area->x1; + ret.y += area->y1; + + return ret; +} + + +/** + * @brief get the icon position of area + * @param area point to area + * @param icon point to icon + * @param offset offset + * @param type align type + */ +sgl_pos_t sgl_get_icon_pos(sgl_area_t *area, const sgl_icon_pixmap_t *icon, int16_t offset, sgl_align_type_t type) +{ + SGL_ASSERT(area != NULL && icon != NULL); + sgl_pos_t ret = {.x = 0, .y = 0}; + sgl_size_t parent_size = { + .w = area->x2 - area->x1 + 1, + .h = area->y2 - area->y1 + 1, + }; + + sgl_size_t text_size = { + .w = icon->width + offset, + .h = icon->height, + }; + + ret = sgl_get_align_pos(&parent_size, &text_size, type); + ret.x += area->x1; + ret.y += area->y1; + + return ret; +} + + +/** + * @brief Set the alignment position of the object relative to its parent object. + * @param obj The object to set the alignment position. + * @param type The alignment type. + * @return none + * @note type should be one of the sgl_align_type_t values: + * - SGL_ALIGN_CENTER : Center the object in the parent object. + * - SGL_ALIGN_TOP_MID : Align the object at the top middle of the parent object. + * - SGL_ALIGN_TOP_LEFT : Align the object at the top left of the parent object. + * - SGL_ALIGN_TOP_RIGHT : Align the object at the top right of the parent object. + * - SGL_ALIGN_BOT_MID : Align the object at the bottom middle of the parent object. + * - SGL_ALIGN_BOT_LEFT : Align the object at the bottom left of the parent object. + * - SGL_ALIGN_BOT_RIGHT : Align the object at the bottom right of the parent object. + * - SGL_ALIGN_LEFT_MID : Align the object at the left middle of the parent object. + * - SGL_ALIGN_RIGHT_MID : Align the object at the right middle of the parent object. + */ +void sgl_obj_set_pos_align(sgl_obj_t *obj, sgl_align_type_t type) +{ + SGL_ASSERT(obj != NULL); + + sgl_size_t p_size = {0}; + sgl_pos_t p_pos = {0}; + sgl_pos_t obj_pos = {0}; + sgl_size_t obj_size = { + .w = obj->coords.x2 - obj->coords.x1 + 1, + .h = obj->coords.y2 - obj->coords.y1 + 1, + }; + + p_size = (sgl_size_t){ + .w = obj->parent->coords.x2 - obj->parent->coords.x1 + 1, + .h = obj->parent->coords.y2 - obj->parent->coords.y1 + 1, + }; + p_pos = (sgl_pos_t){ + .x = obj->parent->coords.x1, + .y = obj->parent->coords.y1, + }; + + obj_pos = sgl_get_align_pos(&p_size, &obj_size, type); + + sgl_obj_set_abs_pos(obj, p_pos.x + obj_pos.x, p_pos.y + obj_pos.y); +} + + +/** + * @brief Set the alignment position of the object relative to sibling object. + * @param ref The reference object, it should be the sibling object. + * @param obj The object to set the alignment position. + * @param type The alignment type. + * @return none + * @note type should be one of the sgl_align_type_t values: + * - SGL_ALIGN_VERT_LEFT : Align the object at the left side of the reference object. + * - SGL_ALIGN_VERT_RIGHT : Align the object at the right side of the reference object. + * - SGL_ALIGN_VERT_MID : Align the object at the middle of the reference object. + * - SGL_ALIGN_HORIZ_TOP : Align the object at the top side of the reference object. + * - SGL_ALIGN_HORIZ_BOT : Align the object at the bottom side of the reference object. + * - SGL_ALIGN_HORIZ_MID : Align the object at the middle of the reference object. + */ +void sgl_obj_set_pos_align_ref(sgl_obj_t *ref, sgl_obj_t *obj, sgl_align_type_t type) +{ + SGL_ASSERT(ref != NULL && obj != NULL); + + if (unlikely(ref == obj->parent)) { + sgl_obj_set_pos_align(obj, type); + return; + } + + int16_t ref_w = ref->coords.x2 - ref->coords.x1 + 1; + int16_t obj_w = obj->coords.x2 - obj->coords.x1 + 1; + int16_t ref_h = ref->coords.y2 - ref->coords.y1 + 1; + int16_t obj_h = obj->coords.y2 - obj->coords.y1 + 1; + + switch (type) { + case SGL_ALIGN_VERT_MID: + obj->coords.x1 = ref->coords.x1 + (ref_w - obj_w) / 2; + obj->coords.x2 = obj->coords.x1 + obj_w - 1; + break; + + case SGL_ALIGN_VERT_LEFT: + obj->coords.x1 = ref->coords.x1; + obj->coords.x2 = obj->coords.x1 + obj_w - 1; + break; + + case SGL_ALIGN_VERT_RIGHT: + obj->coords.x1 = ref->coords.x2 - obj_w; + obj->coords.x2 = obj->coords.x1 + obj_w - 1; + break; + + case SGL_ALIGN_HORIZ_MID: + obj->coords.y1 = ref->coords.y1 + (ref_h - obj_h) / 2; + obj->coords.y2 = obj->coords.y1 + obj_h - 1; + break; + + case SGL_ALIGN_HORIZ_TOP: + obj->coords.y1 = ref->coords.y1; + obj->coords.y2 = obj->coords.y1 + obj_h - 1; + break; + + case SGL_ALIGN_HORIZ_BOT: + obj->coords.y1 = ref->coords.y2 - obj_h; + obj->coords.y2 = obj->coords.y1 + obj_h - 1; + break; + + default: + SGL_LOG_WARN("invalid align type"); + break; + } +} + + +/** + * @brief draw object slice completely + * @param obj it should point to active root object + * @param surf surface that draw to + * @param dirty_h dirty height + * @return none + */ +static inline void draw_obj_slice(sgl_obj_t *obj, sgl_surf_t *surf) +{ + int top = 0; + sgl_event_t evt; + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + + SGL_ASSERT(obj != NULL); + stack[top++] = obj; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + if (sgl_obj_is_hidden(obj)) { + continue; + } + + if (sgl_surf_area_is_overlap(surf, &obj->area)) { + evt.type = SGL_EVENT_DRAW_MAIN; + SGL_ASSERT(obj->construct_fn != NULL); + obj->construct_fn(surf, obj, &evt); + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + } + } + + /* flush dirty area into screen */ + sgl_fbdev_flush_area((sgl_area_t*)surf, surf->buffer); +} + + +/** + * @brief calculate dirty area by for each all object that is dirty and visible + * @param obj it should point to active root object + * @return none + * @note if there is no dirty area, the dirty area will remain unchanged + */ +static inline void sgl_dirty_area_calculate(sgl_obj_t *obj) +{ + sgl_obj_t *stack[SGL_OBJ_DEPTH_MAX]; + int top = 0; + stack[top++] = obj; + + /* for each all object from the first task of page */ + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + + /* if sibling exists, push it to stack, it will be pop in next loop */ + if (obj->sibling != NULL) { + stack[top++] = obj->sibling; + } + + /* if object is hidden, skip it */ + if (unlikely(sgl_obj_is_hidden(obj))) { + continue; + } + + /* check if obj is destroyed */ + if (unlikely(sgl_obj_is_destroyed(obj))) { + /* merge destroy area */ + sgl_dirty_area_push(&obj->area); + + sgl_event_t evt = { + .type = SGL_EVENT_DESTROYED, + }; + + /* check construct function */ + SGL_ASSERT(obj->construct_fn != NULL); + obj->construct_fn(NULL, obj, &evt); + + /* remove obj from parent */ + sgl_obj_remove(obj); + + /* free obj resource */ + sgl_obj_free(obj); + + /* object is destroyed, skip */ + continue; + } + + /* check child need init coords */ + if (unlikely(sgl_obj_is_needinit(obj))) { + sgl_event_t evt = { + .type = SGL_EVENT_DRAW_INIT, + }; + + /* check construct function */ + SGL_ASSERT(obj->construct_fn != NULL); + obj->construct_fn(NULL, obj, &evt); + /* maybe no need to clear flag */ + sgl_obj_clear_needinit(obj); + } + + /* check child dirty and merge all dirty area */ + if (sgl_obj_is_dirty(obj)) { + /* merge dirty area */ + sgl_dirty_area_push(&obj->area); + + sgl_area_t fill_area = sgl_obj_get_fill_rect(obj->parent); + /* update obj area */ + if (unlikely(!sgl_area_clip(&fill_area, &obj->coords, &obj->area))) { + sgl_area_init(&obj->area); + sgl_obj_clear_dirty(obj); + continue; + } + + /* merge dirty area */ + sgl_dirty_area_push(&obj->area); + + /* clear dirty flag */ + sgl_obj_clear_dirty(obj); + } + + if (obj->child != NULL) { + stack[top++] = obj->child; + } + } +} + + +/** + * @brief sgl to draw complete frame + * @param fbdev point to frame buffer device + * @return none + * @note this function should be called in deamon thread or cyclic thread + */ +static inline void sgl_draw_task(sgl_fbdev_t *fbdev) +{ + sgl_surf_t *surf = &fbdev->surf; + sgl_obj_t *head = fbdev->active; + sgl_area_t *dirty = NULL; + + /* dirty area number must less than SGL_DIRTY_AREA_MAX */ + for (int i = 0; i < fbdev->dirty_num; i++) { + dirty = &fbdev->dirty[i]; + surf->dirty = dirty; + +#if (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) + sgl_area_t screen = { .x1 = 0, .y1 = 0, .x2 = SGL_SCREEN_WIDTH - 1, .y2 = SGL_SCREEN_HEIGHT - 1 }; + sgl_area_selfclip(dirty, &screen); +#endif + + /* check dirty area, ensure it is valid */ + SGL_ASSERT(dirty != NULL && dirty->x1 >= 0 && dirty->y1 >= 0 && dirty->x2 < SGL_SCREEN_WIDTH && dirty->y2 < SGL_SCREEN_HEIGHT); + +#if (!CONFIG_SGL_USE_FBDEV_VRAM) + + uint16_t draw_h = 0; + surf->h = dirty->y2 - dirty->y1 + 1; + + surf->x1 = dirty->x1; + surf->y1 = dirty->y1; + surf->x2 = dirty->x2; + surf->w = surf->x2 - surf->x1 + 1; + surf->h = sgl_min(surf->size / surf->w, (uint32_t)(dirty->y2 - dirty->y1 + 1)); + + SGL_LOG_TRACE("[fb:%d]sgl_draw_task: dirty area x1:%d y1:%d x2:%d y2:%d", fbdev->fb_swap, dirty->x1, dirty->y1, dirty->x2, dirty->y2); + + while (surf->y1 <= dirty->y2) { + draw_h = sgl_min(dirty->y2 - surf->y1 + 1, surf->h); + surf->y2 = surf->y1 + draw_h - 1; + + /* wait current framebuffer for ready */ + while (sgl_fbdev_flush_wait_ready(fbdev)); + + /* reset current framebuffer ready flag */ + fbdev->fb_status = (fbdev->fb_status & (2 - fbdev->fb_swap)); + + /* draw object slice until the dirty area is finished */ + draw_obj_slice(head, surf); + surf->y1 += draw_h; + } +#else + /* check dirty area, ensure it is valid */ + SGL_ASSERT(dirty != NULL && dirty->x1 >= 0 && dirty->y1 >= 0 && dirty->x2 < SGL_SCREEN_WIDTH && dirty->y2 < SGL_SCREEN_HEIGHT); + + SGL_LOG_TRACE("[fb:%d]sgl_draw_task: dirty area x1:%d y1:%d x2:%d y2:%d", fbdev->fb_swap, dirty->x1, dirty->y1, dirty->x2, dirty->y2); + draw_obj_slice(head, surf); +#endif + } + /* clear dirty area */ + fbdev->dirty_num = 0; +} + + +/** + * @brief sgl task handle function with sync mode + * @param none + * @return none + * @note you can call this function for force update screen + */ +void sgl_task_handle_sync(void) +{ + /* event task */ + sgl_event_task(); + +#if (CONFIG_SGL_ANIMATION) + sgl_anim_task(); +#endif // !CONFIG_SGL_ANIMATION + + /* foreach all object tree and calculate dirty area */ + sgl_dirty_area_calculate(sgl_system.fbdev.active); + + /* draw all object into screen */ + sgl_draw_task(&sgl_system.fbdev); +} diff --git a/User/system/sgl/core/sgl_event.c b/User/system/sgl/core/sgl_event.c new file mode 100644 index 0000000..d8a1afa --- /dev/null +++ b/User/system/sgl/core/sgl_event.c @@ -0,0 +1,437 @@ +/* source/core/sgl_event.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + + +/* define event queue size */ +#define SGL_EVENT_QUEUE_SIZE (CONFIG_SGL_EVENT_QUEUE_SIZE) +#define SGL_EVENT_QUEUE_SIZE_MASK (SGL_EVENT_QUEUE_SIZE - 1) + +/** + * @brief event queue struct + * @buffer: event buffer to save all event data + * @head: event queue head which is used to push event + * @tail: event queue tail which is used to pop event + * @count: event queue count which have been pushed + */ +typedef struct event_queue { + sgl_event_t buffer[SGL_EVENT_QUEUE_SIZE]; + uint16_t head; + uint16_t tail; +} event_queue_t; + + +/** + * @brief event context struct + * @last_click: last click object which may be lost event + * @last_touch: last touch position + * @evtq: event queue + */ +static struct event_context { + struct sgl_obj *last_click; + sgl_event_pos_t last_touch; + event_queue_t evtq; +} evt_ctx; + + +/** + * @brief Initialize the event queue + * @param none + * @return 0 on success, -1 on failure + * @note !!!!!! the SGL_EVENT_QUEUE_SIZE must be power of 2 !!!!!! + * You must check the return value of this function. + */ +int sgl_event_queue_init(void) +{ + if (!sgl_is_pow2(SGL_EVENT_QUEUE_SIZE)) { + SGL_LOG_ERROR("The capacity must be power of 2"); + return -1; + } + + evt_ctx.evtq.head = evt_ctx.evtq.tail = 0; + return 0; +} + + +/** + * @brief Check whether the event queue is empty + * @param none + * @return true if the event queue is empty, false otherwise + */ +static inline bool sgl_event_queue_is_empty(void) +{ + return evt_ctx.evtq.head == evt_ctx.evtq.tail; +} + + +/** + * @brief Check whether the event queue is full + * @param none + * @return true if the event queue is full, false otherwise + */ +static inline bool sgl_event_queue_is_full(void) +{ + uint32_t next_head = (evt_ctx.evtq.head + 1) & SGL_EVENT_QUEUE_SIZE_MASK; + return next_head == evt_ctx.evtq.tail; +} + + +/** + * @brief Push an event into the event queue + * @param event The event to be pushed + * @return 0 on success, -1 on failure + */ +void sgl_event_queue_push(sgl_event_t event) +{ + if (unlikely(sgl_event_queue_is_full())) { + SGL_LOG_ERROR("Event queue is full, maybe system is too slow"); + return; + } + + evt_ctx.evtq.buffer[evt_ctx.evtq.head] = event; + evt_ctx.evtq.head = ((evt_ctx.evtq.head + 1) & SGL_EVENT_QUEUE_SIZE_MASK); +} + + +/** + * @brief Pop an event from the event queue + * @param out_event The event to be popped + * @return 0 on success, -1 on failure + */ +static inline int sgl_event_queue_pop(sgl_event_t* out_event) +{ + if (sgl_event_queue_is_empty()) { + return -1; + } + + *out_event = evt_ctx.evtq.buffer[evt_ctx.evtq.tail]; + evt_ctx.evtq.tail = ((evt_ctx.evtq.tail + 1) & SGL_EVENT_QUEUE_SIZE_MASK); + return 0; +} + + +/** + * @brief Check whether the position is focus on the object + * @param pos The position to be checked + * @param rect The rectangle of the object + * @param radius The radius of the object + * @return true if the position is focus on the object, false otherwise + */ +static bool pos_is_focus_on_obj(sgl_event_pos_t *pos, sgl_rect_t *rect, int16_t radius) +{ + if (pos->x < rect->x1 || pos->x > rect->x2 || pos->y < rect->y1 || pos->y > rect->y2) { + return false; + } + else if(radius == 0) { + return true; + } + + if ((pos->x >= rect->x1 + radius) && (pos->x <= rect->x2 - radius)) { + return true; + } + else if ((pos->y >= rect->y1 + radius) && (pos->y <= rect->y2 - radius)) { + return true; + } + + if (pos->x <= rect->x1 + radius && pos->y <= rect->y1 + radius) { + int16_t dx = pos->x - (rect->x1 + radius); + int16_t dy = pos->y - (rect->y1 + radius); + return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius); + } + else if (pos->x >= rect->x2 - radius && pos->y <= rect->y1 + radius) { + int16_t dx = pos->x - (rect->x2 - radius); + int16_t dy = pos->y - (rect->y1 + radius); + return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius); + } + else if (pos->x <= rect->x1 + radius && pos->y >= rect->y2 - radius) { + int16_t dx = pos->x - (rect->x1 + radius); + int16_t dy = pos->y - (rect->y2 - radius); + return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius); + } + else if (pos->x >= rect->x2 - radius && pos->y >= rect->y2 - radius) { + int16_t dx = pos->x - (rect->x2 - radius); + int16_t dy = pos->y - (rect->y2 - radius); + return sgl_pow2(dx) + sgl_pow2(dy) <= sgl_pow2(radius); + } + + return false; +} + + +/** + * @brief check whether the position is clicked on the object + * @param pos The position to be clicked + * @return The object that is clicked on, NULL if no object is clicked + */ +static struct sgl_obj* click_detect_object(sgl_event_pos_t *pos) +{ + struct sgl_obj *stack[SGL_OBJ_DEPTH_MAX], *obj = sgl_screen_act()->child, *find = NULL; + int top = 0; + + if (unlikely(obj == NULL)) { + return NULL; + } + stack[top++] = obj; + + while (top > 0) { + SGL_ASSERT(top < SGL_OBJ_DEPTH_MAX); + obj = stack[--top]; + if (sgl_obj_has_sibling(obj)) { + stack[top++] = obj->sibling; + } + + if (unlikely(sgl_obj_is_hidden(obj))) { + continue; + } + + if (pos_is_focus_on_obj(pos, &obj->coords, obj->radius)) { + find = obj; + if (sgl_obj_has_child(obj)) { + stack[top++] = obj->child; + } + } + } + + /** + * if the object is clickable, return it, otherwise return its parent + * because the object may be a label attached to the object + */ + if (find != NULL) { + return sgl_obj_is_clickable(find) ? find : (sgl_obj_is_clickable(find->parent) ? find->parent : NULL); + } + + return find; +} + + +/** + * @brief Handle the position event + * @param pos The position to be handled + * @param type The type of the event + * @return none + */ +void sgl_event_send_pos(sgl_event_pos_t pos, sgl_event_type_t type) +{ + sgl_event_t event = { + .obj = NULL, + .type = type, + .pos = pos, + }; + + if (type == SGL_EVENT_PRESSED) { + evt_ctx.last_touch = pos; + } + + sgl_event_queue_push(event); +} + + +/** + * @brief get information of motion event type + * @param evt [in][out] event to be handled + * @return none + */ +static void sgl_get_move_info(sgl_event_t *evt) +{ + int16_t dx = evt->pos.x - evt_ctx.last_touch.x; + int16_t dy = evt->pos.y - evt_ctx.last_touch.y; + + if (sgl_abs(dx) > sgl_abs(dy)) { + if (dx > 0) { + evt->type = SGL_EVENT_MOVE_RIGHT; + evt->distance = dx; + } + else { + evt->type = SGL_EVENT_MOVE_LEFT; + evt->distance = -dx; + } + } + else { + if (dy > 0) { + evt->type = SGL_EVENT_MOVE_DOWN; + evt->distance = dy; + } + else { + evt->type = SGL_EVENT_MOVE_UP; + evt->distance = -dy; + } + } + + evt_ctx.last_touch = evt->pos; +} + + +/** + * @brief All event task in SGL, this function will traverse all elements in the event queue, + * respond to each element with an event, so that all events will trigger and point to the + * corresponding callback function + * @param none + * @return none +*/ +void sgl_event_task(void) +{ + sgl_event_t evt; + struct sgl_obj *obj = NULL; + + /* Get event from event queue */ + while (sgl_event_queue_pop(&evt) == 0) { + obj = evt.obj; + + /* if obj is NULL, it means the event from the input device */ + if (obj == NULL) { + if (evt.type != SGL_EVENT_MOTION) { + obj = click_detect_object(&evt.pos); + } else { + obj = evt_ctx.last_click; + sgl_get_move_info(&evt); + } + } + + if (obj) { + evt.pos.x = sgl_clamp(evt.pos.x, obj->coords.x1, obj->coords.x2); + evt.pos.y = sgl_clamp(evt.pos.y, obj->coords.y1, obj->coords.y2); + + if (evt.type == SGL_EVENT_PRESSED) { + if (obj->pressed) { + continue; + } + obj->pressed = true; + evt_ctx.last_click = obj; + } + else if (evt.type == SGL_EVENT_RELEASED) { + if (!obj->pressed) { + if (evt_ctx.last_click && evt_ctx.last_click != obj) { + evt.obj = evt_ctx.last_click; + sgl_event_queue_push(evt); + } + continue; + } + obj->pressed = false; + evt_ctx.last_click = NULL; + } + + SGL_ASSERT(obj->construct_fn); + evt.param = obj->event_data; + evt.obj = obj; + obj->construct_fn(NULL, obj, &evt); + + /* call user event function */ + if(obj->event_fn) { + obj->event_fn(&evt); + } + } + else { + SGL_LOG_TRACE("pos is out of object or no event_lost, skip event"); + if (evt.type == SGL_EVENT_RELEASED && evt_ctx.last_click != NULL) { + evt.obj = evt_ctx.last_click; + sgl_event_queue_push(evt); + } + } + } +} + + +/** + * @brief Touch event read, this function will be called by user + * @param x: touch x position + * @param y: touch y position + * @param flag: touch flag, it means touch event down or up: + * true : touch down + * false: touch up + * @return none + * @note: for example, you can call it in 30ms tick handler function + * void example_30ms_tick_handler(void) + * { + * int pos_x, pos_y; + * bool button_status; + * + * bsp_touch_read_pos(&pos_x, &pos_y); + * button_status = bsp_touch_read_status(); + * + * sgl_event_pos_input(pos_x, pos_y, button_status); + * } + */ +void sgl_event_pos_input(int16_t x, int16_t y, bool flag) +{ + static sgl_event_pos_t last_press, last_motion; + static uint32_t act_count = 0; + sgl_event_pos_t pos = { .x = x, .y = y }; + + /* rotate touch position */ +#if (CONFIG_SGL_FBDEV_ROTATION != 0) +#if (CONFIG_SGL_FBDEV_ROTATION == 90) + pos.x = sgl_min(SGL_SCREEN_WIDTH - y, SGL_SCREEN_WIDTH - 1); + pos.y = sgl_min(x, SGL_SCREEN_HEIGHT - 1); +#elif (CONFIG_SGL_FBDEV_ROTATION == 180) + pos.x = SGL_SCREEN_WIDTH - x - 1; + pos.y = SGL_SCREEN_HEIGHT - y - 1; +#elif (CONFIG_SGL_FBDEV_ROTATION == 270) + pos.x = sgl_min(y, SGL_SCREEN_WIDTH - 1); + pos.y = sgl_min(SGL_SCREEN_HEIGHT - x, SGL_SCREEN_HEIGHT - 1); +#else + #error "CONFIG_SGL_FBDEV_ROTATION is invalid rotation value (only 0/90/180/270 supported)" +#endif +#endif //!CONFIG_SGL_FBDEV_ROTATION + + if (flag) { + if (!act_count) { + act_count = 1; + sgl_event_send_pos(pos, SGL_EVENT_PRESSED); + last_press = pos; + SGL_LOG_INFO("Touch SGL_EVENT_PRESSED x: %d, y: %d", pos.x, pos.y); + } + else { + sgl_event_send_pos(pos, SGL_EVENT_MOTION); + last_motion = pos; + SGL_LOG_INFO("Touch SGL_EVENT_MOTION x: %d, y: %d", pos.x, pos.y); + } + + act_count ++; + } + else { + if (act_count) { + SGL_LOG_INFO("Touch action count: %d", act_count); + if (last_press.x == last_motion.x && last_press.y == last_motion.y) { + if (act_count < SGL_EVENT_CLICK_INTERVAL) { + sgl_event_send_pos(last_press, SGL_EVENT_CLICKED); + SGL_LOG_INFO("Touch SGL_EVENT_CLICKED x: %d, y: %d", last_press.x, last_press.y); + } + else { + sgl_event_send_pos(last_press, SGL_EVENT_LONG_CLICKED); + SGL_LOG_INFO("Touch SGL_EVENT_LONG_CLICKED x: %d, y: %d", last_press.x, last_press.y); + } + } + + act_count = 0; + sgl_event_send_pos(last_motion, SGL_EVENT_RELEASED); + SGL_LOG_INFO("Touch SGL_EVENT_RELEASED x: %d, y: %d", last_motion.x, last_motion.y); + } + } +} diff --git a/User/system/sgl/core/sgl_log.c b/User/system/sgl/core/sgl_log.c new file mode 100644 index 0000000..0aa655d --- /dev/null +++ b/User/system/sgl/core/sgl_log.c @@ -0,0 +1,78 @@ +/* source/core/sgl_log.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + + +#if CONFIG_SGL_DEBUG + +/** + * @brief sgl log printing function, used to print debugging information. Note that this function + * should only be called in debugging mode, otherwise it may affect system real-time + * performance due to long execution time + * @param level: log level, such as, INFO, USER... + * @param format: log content + * @return none +*/ +void sgl_log(const char *level, const char * format, ...) +{ + char buffer[120]; + int tail = 0; + int pref_size = strlen(level); + + strcpy(buffer, level); + + va_list va; + va_start(va, format); + sgl_vsnprintf(buffer + pref_size, sizeof(buffer), format, va); + va_end(va); + + tail = strlen(buffer); + memcpy(&buffer[tail], &"\r\n"SGL_LOG_NONE, strlen("\r\n"SGL_LOG_NONE)); + buffer[tail + strlen("\r\n"SGL_LOG_NONE)] = 0; + + sgl_log_stdout(buffer); +} + + +/** + * @brief sgl assert handler, used to handle assertions + * @param file: file name + * @param func: function name + * @param line: line number + * @return none +*/ +void sgl_assert_handler(const char *file, const char *func, int line) +{ + sgl_log(SGL_ASSERT_FLAG, "file: %s, function: %s, line: %d", file, func, line); + while (1) { + + }; +} + +#endif // !CONFIG_SGL_DEBUG diff --git a/User/system/sgl/core/sgl_math.c b/User/system/sgl/core/sgl_math.c new file mode 100644 index 0000000..d2dc187 --- /dev/null +++ b/User/system/sgl/core/sgl_math.c @@ -0,0 +1,434 @@ +/* source/core/sgl_math.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + + +/** + * @brief sine table + * @note the table is used to calculate the sine of an angle + */ +static const int16_t sin0_90_table[] = { + 0, 572, 1144, 1715, 2286, 2856, 3425, 3993, 4560, 5126, 5690, 6252, 6813, 7371, 7927, 8481, + 9032, 9580, 10126, 10668, 11207, 11743, 12275, 12803, 13328, 13848, 14364, 14876, 15383, 15886, 16383, 16876, + 17364, 17846, 18323, 18794, 19260, 19720, 20173, 20621, 21062, 21497, 21925, 22347, 22762, 23170, 23571, 23964, + 24351, 24730, 25101, 25465, 25821, 26169, 26509, 26841, 27165, 27481, 27788, 28087, 28377, 28659, 28932, 29196, + 29451, 29697, 29934, 30162, 30381, 30591, 30791, 30982, 31163, 31335, 31498, 31650, 31794, 31927, 32051, 32165, + 32269, 32364, 32448, 32523, 32587, 32642, 32687, 32722, 32747, 32762, 32767 +}; + + +/** + * @brief sqrt table, if the number less than 1024, the sqrt root will get by the table + */ +static const uint8_t sqrt_error_table[] = { + 0x00,0x00,0x6a,0xbb,0x00,0x3c,0x73,0xa5,0xd4,0x00,0x29,0x51,0x76,0x9b,0xbd,0xdf, + 0x00,0x1f,0x3e,0x5b,0x78,0x95,0xb0,0xcb,0xe6,0x00,0x19,0x32,0x4a,0x62,0x7a,0x91, + 0xa8,0xbe,0xd4,0xea,0x00,0x15,0x2a,0x3e,0x53,0x67,0x7b,0x8e,0xa2,0xb5,0xc8,0xdb, + 0xed,0x00,0x12,0x24,0x36,0x47,0x59,0x6a,0x7b,0x8c,0x9d,0xae,0xbe,0xcf,0xdf,0xef, + 0x00,0x0f,0x1f,0x2f,0x3f,0x4e,0x5d,0x6d,0x7c,0x8b,0x9a,0xa9,0xb7,0xc6,0xd4,0xe3, + 0xf1,0x00,0x0e,0x1c,0x2a,0x38,0x46,0x53,0x61,0x6f,0x7c,0x8a,0x97,0xa4,0xb2,0xbf, + 0xcc,0xd9,0xe6,0xf3,0x00,0x0c,0x19,0x26,0x32,0x3f,0x4b,0x58,0x64,0x70,0x7c,0x89, + 0x95,0xa1,0xad,0xb9,0xc5,0xd1,0xdc,0xe8,0xf4,0x00,0x0b,0x17,0x22,0x2e,0x39,0x44, + 0x50,0x5b,0x66,0x72,0x7d,0x88,0x93,0x9e,0xa9,0xb4,0xbf,0xca,0xd5,0xdf,0xea,0xf5, + 0x00,0x0a,0x15,0x1f,0x2a,0x34,0x3f,0x49,0x54,0x5e,0x68,0x73,0x7d,0x87,0x91,0x9c, + 0xa6,0xb0,0xba,0xc4,0xce,0xd8,0xe2,0xec,0xf6,0x00,0x09,0x13,0x1d,0x27,0x30,0x3a, + 0x44,0x4d,0x57,0x61,0x6a,0x74,0x7d,0x87,0x90,0x99,0xa3,0xac,0xb6,0xbf,0xc8,0xd1, + 0xdb,0xe4,0xed,0xf6,0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x51,0x5a,0x63, + 0x6c,0x74,0x7d,0x86,0x8f,0x98,0xa0,0xa9,0xb2,0xbb,0xc3,0xcc,0xd5,0xdd,0xe6,0xee, + 0xf7,0x00,0x08,0x11,0x19,0x21,0x2a,0x32,0x3b,0x43,0x4c,0x54,0x5c,0x65,0x6d,0x75, + 0x7d,0x86,0x8e,0x96,0x9e,0xa7,0xaf,0xb7,0xbf,0xc7,0xcf,0xd7,0xdf,0xe7,0xef,0xf7, + 0x00,0x07,0x0f,0x17,0x1f,0x27,0x2f,0x37,0x3f,0x47,0x4f,0x57,0x5e,0x66,0x6e,0x76, + 0x7e,0x85,0x8d,0x95,0x9c,0xa4,0xac,0xb4,0xbb,0xc3,0xca,0xd2,0xda,0xe1,0xe9,0xf0, + 0xf8,0x00,0x07,0x0f,0x16,0x1e,0x25,0x2c,0x34,0x3b,0x43,0x4a,0x52,0x59,0x60,0x68, + 0x6f,0x76,0x7e,0x85,0x8c,0x94,0x9b,0xa2,0xa9,0xb1,0xb8,0xbf,0xc6,0xcd,0xd5,0xdc, + 0xe3,0xea,0xf1,0xf8,0x00,0x07,0x0e,0x15,0x1c,0x23,0x2a,0x31,0x38,0x3f,0x46,0x4d, + 0x54,0x5b,0x62,0x69,0x70,0x77,0x7e,0x85,0x8c,0x92,0x99,0xa0,0xa7,0xae,0xb5,0xbc, + 0xc2,0xc9,0xd0,0xd7,0xde,0xe4,0xeb,0xf2,0xf9,0x00,0x06,0x0d,0x14,0x1a,0x21,0x28, + 0x2e,0x35,0x3c,0x42,0x49,0x50,0x56,0x5d,0x64,0x6a,0x71,0x77,0x7e,0x84,0x8b,0x92, + 0x98,0x9f,0xa5,0xac,0xb2,0xb9,0xbf,0xc6,0xcc,0xd3,0xd9,0xdf,0xe6,0xec,0xf3,0xf9, + 0x00,0x06,0x0c,0x13,0x19,0x1f,0x26,0x2c,0x32,0x39,0x3f,0x45,0x4c,0x52,0x58,0x5f, + 0x65,0x6b,0x71,0x78,0x7e,0x84,0x8a,0x91,0x97,0x9d,0xa3,0xa9,0xb0,0xb6,0xbc,0xc2, + 0xc8,0xcf,0xd5,0xdb,0xe1,0xe7,0xed,0xf3,0xf9,0x00,0x06,0x0c,0x12,0x18,0x1e,0x24, + 0x2a,0x30,0x36,0x3c,0x42,0x48,0x4e,0x54,0x5a,0x60,0x66,0x6c,0x72,0x78,0x7e,0x84, + 0x8a,0x90,0x96,0x9c,0xa2,0xa8,0xad,0xb3,0xb9,0xbf,0xc5,0xcb,0xd1,0xd7,0xdc,0xe2, + 0xe8,0xee,0xf4,0xfa,0x00,0x05,0x0b,0x11,0x17,0x1d,0x22,0x28,0x2e,0x34,0x39,0x3f, + 0x45,0x4b,0x50,0x56,0x5c,0x62,0x67,0x6d,0x73,0x78,0x7e,0x84,0x89,0x8f,0x95,0x9a, + 0xa0,0xa6,0xab,0xb1,0xb7,0xbc,0xc2,0xc8,0xcd,0xd3,0xd8,0xde,0xe4,0xe9,0xef,0xf4, + 0xfa,0x00,0x05,0x0b,0x10,0x16,0x1b,0x21,0x26,0x2c,0x31,0x37,0x3c,0x42,0x47,0x4d, + 0x52,0x58,0x5d,0x63,0x68,0x6e,0x73,0x79,0x7e,0x84,0x89,0x8e,0x94,0x99,0x9f,0xa4, + 0xaa,0xaf,0xb4,0xba,0xbf,0xc5,0xca,0xcf,0xd5,0xda,0xdf,0xe5,0xea,0xef,0xf5,0xfa, + 0x00,0x05,0x0a,0x0f,0x15,0x1a,0x1f,0x25,0x2a,0x2f,0x35,0x3a,0x3f,0x44,0x4a,0x4f, + 0x54,0x5a,0x5f,0x64,0x69,0x6e,0x74,0x79,0x7e,0x83,0x89,0x8e,0x93,0x98,0x9d,0xa3, + 0xa8,0xad,0xb2,0xb7,0xbd,0xc2,0xc7,0xcc,0xd1,0xd6,0xdc,0xe1,0xe6,0xeb,0xf0,0xf5, + 0xfa,0x00,0x05,0x0a,0x0f,0x14,0x19,0x1e,0x23,0x28,0x2d,0x32,0x38,0x3d,0x42,0x47, + 0x4c,0x51,0x56,0x5b,0x60,0x65,0x6a,0x6f,0x74,0x79,0x7e,0x83,0x88,0x8d,0x92,0x97, + 0x9c,0xa1,0xa6,0xab,0xb0,0xb5,0xba,0xbf,0xc4,0xc9,0xce,0xd3,0xd8,0xdd,0xe2,0xe7, + 0xec,0xf1,0xf6,0xfb,0x00,0x04,0x09,0x0e,0x13,0x18,0x1d,0x22,0x27,0x2c,0x31,0x35, + 0x3a,0x3f,0x44,0x49,0x4e,0x53,0x58,0x5c,0x61,0x66,0x6b,0x70,0x75,0x79,0x7e,0x83, + 0x88,0x8d,0x92,0x96,0x9b,0xa0,0xa5,0xaa,0xae,0xb3,0xb8,0xbd,0xc2,0xc6,0xcb,0xd0, + 0xd5,0xd9,0xde,0xe3,0xe8,0xed,0xf1,0xf6,0xfb,0x00,0x04,0x09,0x0e,0x12,0x17,0x1c, + 0x21,0x25,0x2a,0x2f,0x33,0x38,0x3d,0x42,0x46,0x4b,0x50,0x54,0x59,0x5e,0x62,0x67, + 0x6c,0x70,0x75,0x7a,0x7e,0x83,0x88,0x8c,0x91,0x96,0x9a,0x9f,0xa3,0xa8,0xad,0xb1, + 0xb6,0xbb,0xbf,0xc4,0xc8,0xcd,0xd2,0xd6,0xdb,0xdf,0xe4,0xe9,0xed,0xf2,0xf6,0xfb, + 0x00,0x04,0x09,0x0d,0x12,0x16,0x1b,0x1f,0x24,0x29,0x2d,0x32,0x36,0x3b,0x3f,0x44, + 0x48,0x4d,0x51,0x56,0x5a,0x5f,0x63,0x68,0x6c,0x71,0x75,0x7a,0x7e,0x83,0x87,0x8c, + 0x90,0x95,0x99,0x9e,0xa2,0xa7,0xab,0xb0,0xb4,0xb9,0xbd,0xc1,0xc6,0xca,0xcf,0xd3, + 0xd8,0xdc,0xe1,0xe5,0xe9,0xee,0xf2,0xf7,0xfb,0x00,0x04,0x08,0x0d,0x11,0x16,0x1a, + 0x1e,0x23,0x27,0x2c,0x30,0x34,0x39,0x3d,0x41,0x46,0x4a,0x4f,0x53,0x57,0x5c,0x60, + 0x64,0x69,0x6d,0x71,0x76,0x7a,0x7e,0x83,0x87,0x8b,0x90,0x94,0x98,0x9d,0xa1,0xa5, + 0xaa,0xae,0xb2,0xb7,0xbb,0xbf,0xc4,0xc8,0xcc,0xd0,0xd5,0xd9,0xdd,0xe2,0xe6,0xea, + 0xee,0xf3,0xf7,0xfb,0x00,0x04,0x08,0x0c,0x11,0x15,0x19,0x1d,0x22,0x26,0x2a,0x2e, + 0x33,0x37,0x3b,0x3f,0x43,0x48,0x4c,0x50,0x54,0x59,0x5d,0x61,0x65,0x69,0x6e,0x72, + 0x76,0x7a,0x7e,0x83,0x87,0x8b,0x8f,0x93,0x98,0x9c,0xa0,0xa4,0xa8,0xac,0xb1,0xb5, + 0xb9,0xbd,0xc1,0xc5,0xca,0xce,0xd2,0xd6,0xda,0xde,0xe3,0xe7,0xeb,0xef,0xf3,0xf7, + 0xfb,0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x25,0x29,0x2d,0x31,0x35,0x39, + 0x3d,0x41,0x45,0x49,0x4e,0x52,0x56,0x5a,0x5e,0x62,0x66,0x6a,0x6e,0x72,0x76,0x7a, + 0x7e,0x83,0x87,0x8b,0x8f,0x93,0x97,0x9b,0x9f,0xa3,0xa7,0xab,0xaf,0xb3,0xb7,0xbb, + 0xbf,0xc3,0xc7,0xcb,0xcf,0xd3,0xd7,0xdb,0xdf,0xe3,0xe7,0xeb,0xef,0xf3,0xf7,0xfb, + 0x00 +}; + + +/** + * the table will used to calculate the square root of a number + */ +static const uint8_t sqrt_error_init_table[32] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, + 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7 +}; + + +/** + * @brief Calculate the sine of an angle + * @param angle: Angle in degrees such 0-359 + * @return sine of the angle from sin0_90_table + * @note This function has implemented angle normalization to the range of 0 to 360 degrees. + */ +int32_t sgl_sin(int16_t angle) +{ + int16_t ret = 0; + + while (angle >= 360) { + angle -= 360; + } + while (angle < 0) { + angle += 360; + } + + if (angle < 0) { + angle = 360 + angle; + } + + if (angle < 90) { + ret = sin0_90_table[angle]; + } + else if (angle >= 90 && angle < 180){ + angle = 180 - angle; + ret = sin0_90_table[angle]; + } + else if (angle >= 180 && angle < 270){ + angle = angle - 180; + ret = -sin0_90_table[angle]; + } + else { + angle = 360 - angle; + ret = -sin0_90_table[angle]; + } + + return ret; +} + + +/** + * @brief Calculate x number square root + * @param x: x number + * @retval x number square root + */ +uint16_t sgl_sqrt(uint32_t x) +{ + uint32_t rem = 0; + uint32_t root = 0; + uint32_t divisor = 0; + + for (int i=0; i<16; i++) { + root <<= 1; + rem = ((rem << 2) + (x >> 30)); + x <<= 2; + divisor = (root<<1) + 1; + + if (divisor <= rem) { + rem -= divisor; + root++; + } + } + return (uint16_t)(root); +} + + +/** + * @brief Calculate error of the square root for a number. + * @param x The number to calculate the error for. + * @return The error of the square root. [0 ~ 255] + */ +uint8_t sgl_sqrt_error(uint32_t x) +{ + uint32_t bsh = (1 << 14); + uint32_t fpr = 0; + uint32_t osh = 0; + uint32_t bod; + + if (x < 1025) { + return sqrt_error_table[x]; + } + else if (x > (1 << 30)) { + return 0; + } + + int32_t index = 0; + uint32_t xp = x; + + if ((xp & 0xFFFF0000) == 0) { index += 16; xp <<= 16; } + if ((xp & 0xFF000000) == 0) { index += 8; xp <<= 8; } + if ((xp & 0xF0000000) == 0) { index += 4; xp <<= 4; } + if ((xp & 0xC0000000) == 0) { index += 2; xp <<= 2; } + if ((xp & 0x80000000) == 0) { index += 1; } + + osh = sqrt_error_init_table[31 - index]; + bsh = 1 << (2 * osh + 14); + + do { + bod = bsh + fpr; + if (x >= bod) { + x -= bod; + fpr = bsh + bod; + } + x <<= 1; + }while (bsh >>= 1); + + return fpr>>osh; +} + + +/** + * @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm + * implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm) + * + * @param x: The x coordinate on a circle + * @param y: The y coordinate on a circle + * @return angle + * @note return angle [-32767 ~ 32767] + */ +int32_t sgl_atan2_raw(int x, int y) +{ + int32_t ret; + + if (y == 0) { + if (x > 0) { + ret = -32767; + } + else { + ret = 32767; + } + } + else { + ret = (x << 8) / y; + } + if (y > 0) { + ret += 32767; + } + else { + ret -= 32767; + } + + return ret; +} + + +/** + * @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm + * implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm) + * + * @param x: The x coordinate on a circle + * @param y: The y coordinate on a circle + * @return angle + * @note return angle [0 ~ 359] +*/ +uint16_t sgl_atan2_angle(int x, int y) +{ + unsigned char negflag; + unsigned char tempdegree; + unsigned char comp; + unsigned int degree; + unsigned int ux; + unsigned int uy; + + negflag = 0; + if (x < 0) { + negflag += 0x01; + x = (0 - x); + } + ux = x; + if (y < 0) { + negflag += 0x02; + y = (0 - y); + } + uy = y; + + if (ux > uy) { + degree = (uy * 45) / ux; + negflag += 0x10; + } + else { + degree = (ux * 45) / uy; + } + + comp = 0; + tempdegree = degree; + if (tempdegree > 22) { + if (tempdegree <= 44) comp++; + if (tempdegree <= 41) comp++; + if (tempdegree <= 37) comp++; + if (tempdegree <= 32) comp++; + } + else { + if (tempdegree >= 2) comp++; + if (tempdegree >= 6) comp++; + if (tempdegree >= 10) comp++; + if (tempdegree >= 15) comp++; + } + degree += comp; + + if (negflag & 0x10) degree = (90 - degree); + + if (negflag & 0x02) { + if (negflag & 0x01) + degree = (180 + degree); + else + degree = (180 - degree); + } + else { + if (negflag & 0x01) + degree = (360 - degree); + } + return degree; +} + + +/** + * @brief Split the length into n parts, with the weight of each part. + * @param weight: The weight of each part. + * @param count: The count of parts. + * @param length: The length to split. + * @param gap: The gap between each part. + * @param out: The length of each part. + * @note The error accumulation method of Bresenham's algorithm + */ +void sgl_split_len(const uint8_t *weight, int count, int16_t length, int16_t gap, int16_t *out) +{ + int16_t total_w = 0, span = 0, accumulated = 0, error = 0; + for (int i = 0; i < count; i++) { + total_w += weight[i]; + } + + span = length - gap * (count + 1); + + for (int i = 0; i < count; i++) { + int numerator = weight[i] * span; + out[i] = numerator / total_w; + error += numerator % total_w; + + if (error >= total_w) { + out[i] += 1; + error -= total_w; + } + accumulated += out[i]; + } + + error = span - accumulated; + + for (int i = 0; i < count && error > 0; i++) { + out[i] += 1; + error --; + } + + for (int i = 0; i < count && error < 0; i++) { + out[i] -= 1; + error ++; + } +} + + +/** + * @brief Split the length into n parts, with the weight of each part. + * @param length: The length to split. + * @param count: The count of parts. + * @param gap: The gap between each part. + * @param out: The length of each part. + * @note The average method of Bresenham's algorithm + */ +void sgl_split_len_avg(int length, int count, int16_t gap, int16_t *out) +{ + int16_t available_length = length - (count + 1) * gap; + int16_t base = available_length / count; + int16_t remainder = available_length % count; + + int16_t error = 0; + for (int i = 0; i < count; i++) { + out[i] = base; + error += remainder; + + if (error > count / 2) { + out[i] += 1; + error -= count; + } + } +} + + +/* Random number generator */ +static size_t rand_next = 1; + +/** + * @brief Generate a random number. + * @param none + * @return Random number. + * @note The random number generator is in the range of [0, 32767]. + */ +int16_t sgl_rand(void) +{ + rand_next = rand_next * 1103515245 + 12345; + return (int16_t)((rand_next >> 16) & 0x7FFF); +} + + +/** + * @brief Set the seed of the random number generator. + * @param seed: The seed of the random number generator. + * @return none + */ +void sgl_srand(unsigned int seed) +{ + rand_next = seed; +} diff --git a/User/system/sgl/core/sgl_misc.c b/User/system/sgl/core/sgl_misc.c new file mode 100644 index 0000000..1f4a85f --- /dev/null +++ b/User/system/sgl/core/sgl_misc.c @@ -0,0 +1,166 @@ +/* source/core/sgl_misc.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#if (CONFIG_SGL_BOOT_LOGO) + +typedef struct sgl_logo { + sgl_obj_t obj; + uint8_t progress; + uint8_t alpha; +}sgl_logo_t; + +#define SGL_LOGO_W (26) +#define SGL_LOGO_H (14) + +const uint8_t sgl_logo_s[][4] = { + {0, 0, 8, 2}, + {0, 2, 2, 8}, + {2, 6, 8, 8}, + {6, 8, 8, 14}, + {0, 12, 6, 14}, +}; + +const uint8_t sgl_logo_g[][4] = { + {9, 0, 17, 2}, + {9, 2, 11, 14}, + {11, 12, 17, 14}, + {15, 6, 17, 12}, + {13, 6, 15, 8}, +}; + +const uint8_t sgl_logo_l[][4] = { + {18, 0, 20, 14}, + {20, 12, 26, 14}, +}; + +static void sgl_logo_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_logo_t *logo = (sgl_logo_t*)obj; + int16_t w = obj->area.x2 - obj->area.x1 + 1; + int16_t h = obj->area.y2 - obj->area.y1 + 1; + + const float scale_x = w / SGL_LOGO_W; + const float scale_y = h / SGL_LOGO_H; + sgl_rect_t rect; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_area_t clip; + + if (!sgl_surf_clip(surf, &obj->area, &clip)) { + return; + } + + for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_s); i++) { + rect.x1 = sgl_logo_s[i][0] * scale_x + obj->area.x1; + rect.y1 = sgl_logo_s[i][1] * scale_y + obj->area.y1; + rect.x2 = sgl_logo_s[i][2] * scale_x + obj->area.x1 - 1; + rect.y2 = sgl_logo_s[i][3] * scale_y + obj->area.y1 - 1; + + sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_RED, SGL_COLOR_BLUE, 0, logo->alpha); + } + + for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_g); i++) { + rect.x1 = sgl_logo_g[i][0] * scale_x + obj->area.x1; + rect.y1 = sgl_logo_g[i][1] * scale_y + obj->area.y1; + rect.x2 = sgl_logo_g[i][2] * scale_x + obj->area.x1 - 1; + rect.y2 = sgl_logo_g[i][3] * scale_y + obj->area.y1 - 1; + + sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_GREEN, SGL_COLOR_BLUE, 0, logo->alpha); + } + + for (uint32_t i = 0; i < SGL_ARRAY_SIZE(sgl_logo_l); i++) { + rect.x1 = sgl_logo_l[i][0] * scale_x + obj->area.x1; + rect.y1 = sgl_logo_l[i][1] * scale_y + obj->area.y1; + rect.x2 = sgl_logo_l[i][2] * scale_x + obj->area.x1 - 1; + rect.y2 = sgl_logo_l[i][3] * scale_y + obj->area.y1 - 1; + + sgl_draw_fill_rect_with_border(surf, &clip, &rect, obj->radius, SGL_COLOR_BLUE, SGL_COLOR_BLUE, 0, logo->alpha); + } + } +} + +sgl_obj_t* sgl_logo_create(sgl_obj_t* parent) +{ + sgl_logo_t *logo = sgl_malloc(sizeof(sgl_logo_t)); + if (logo == NULL) { + SGL_LOG_ERROR("sgl_logo_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(logo, 0, sizeof(sgl_logo_t)); + + sgl_obj_t *obj = &logo->obj; + sgl_obj_init(&logo->obj, parent); + obj->construct_fn = sgl_logo_construct_cb; + logo->alpha = SGL_ALPHA_MAX; + sgl_obj_set_border_width(obj, 0); + return obj; +} + +void sgl_logo_set_alpha(sgl_obj_t* obj, uint8_t alpha) +{ + sgl_logo_t *logo = (sgl_logo_t*)obj; + logo->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +void sgl_logo_anim(sgl_anim_t *anim, int32_t value) +{ + sgl_obj_t *logo = (sgl_obj_t*)anim->data; + sgl_logo_set_alpha(logo, value); +} + +/** + * @brief to show the sgl logo after sgl init + * @param none + * @return none + * @note: you can call this function in your main function to show the sgl logo + */ +void sgl_boot_logo(void) +{ + sgl_obj_t *logo = sgl_logo_create(NULL); + sgl_obj_set_size(logo, SGL_SCREEN_WIDTH / 3, SGL_SCREEN_HEIGHT / 3); + sgl_obj_set_pos_align(logo, SGL_ALIGN_CENTER); + sgl_obj_set_radius(logo, 0); + + sgl_anim_t *anim = sgl_anim_create(); + sgl_anim_set_data(anim, logo); + sgl_anim_set_act_duration(anim, 1000); + sgl_anim_set_start_value(anim, SGL_ALPHA_MAX); + sgl_anim_set_end_value(anim, SGL_ALPHA_MIN); + sgl_anim_set_path(anim, sgl_logo_anim, SGL_ANIM_PATH_LINEAR); + sgl_anim_start(anim, SGL_ANIM_REPEAT_ONCE); + + while (!sgl_anim_is_finished(anim)) { + sgl_task_handle(); + } + + sgl_anim_delete(anim); + sgl_obj_delete(logo); +} + +#endif // !CONFIG_SGL_BOOT_LOGO diff --git a/User/system/sgl/core/sgl_snprintf.c b/User/system/sgl/core/sgl_snprintf.c new file mode 100644 index 0000000..c175539 --- /dev/null +++ b/User/system/sgl/core/sgl_snprintf.c @@ -0,0 +1,306 @@ +/* source/core/sgl_snprintf.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * @brief append a character to the buffer + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param c character to append + */ +static inline void append_char(char *buf, size_t size, size_t *pos, char c) +{ + if (*pos + 1 < size) { + buf[*pos] = c; + } + (*pos)++; +} + +/** + * @brief append a string to the buffer + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param s string to append + */ +static inline void append_str(char *buf, size_t size, size_t *pos, const char* s) +{ + while (*s) append_char(buf, size, pos, *s++); +} + +/** + * @brief pad alignment characters (default: space) to the buffer + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param pad_len number of padding characters to append + * @param pad_char padding character (default: ' ') + */ +static inline void pad_align(char *buf, size_t size, size_t *pos, size_t pad_len, char pad_char) +{ + for (size_t i = 0; i < pad_len; i++) { + append_char(buf, size, pos, pad_char); + } +} + +/** + * @brief calculate the length of an integer when converted to string + * @param val integer value + * @return number of characters of the integer string + */ +static inline size_t int_str_len(int val) +{ + if (val == 0) return 1; // Special case: 0 has length 1 + + size_t len = 0; + bool neg = val < 0; + + if (neg) val = -val; + + do { + len++; + val /= 10; + } while (val); + + return neg ? len + 1 : len; // Add 1 for negative sign +} + +/** + * @brief append an integer to the buffer with left/right alignment support + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param val integer to append + * @param width alignment width (0 means no alignment) + * @param left_align whether to use left alignment (true: left, false: right) + */ +static inline void append_int(char *buf, size_t size, size_t *pos, int val, int width, bool left_align) +{ + char tmp[64]; + int i = 0; + bool neg = val < 0; + size_t num_len = int_str_len(val); + size_t pad_len = 0; + + if (width > 0 && (size_t)width > num_len) { + pad_len = (size_t)width - num_len; + } + + if (!left_align && pad_len > 0) { + pad_align(buf, size, pos, pad_len, ' '); + } + + if (neg) val = -val; + + do { + tmp[i++] = '0' + (val % 10); + val /= 10; + } while (val); + + if (neg) tmp[i++] = '-'; + + while (i--) append_char(buf, size, pos, tmp[i]); + + if (left_align && pad_len > 0) { + pad_align(buf, size, pos, pad_len, ' '); + } +} + +/** + * @brief append a hexadecimal number to the buffer + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param val hexadecimal number to append + * @param upper whether to use uppercase letters + */ +static inline void append_hex(char *buf, size_t size, size_t *pos, unsigned int val, bool upper) +{ + char tmp[32]; + int i = 0; + const char *digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + + do { + tmp[i++] = digits[val & 0xF]; + val >>= 4; + } while (val); + + while (i--) append_char(buf, size, pos, tmp[i]); +} + +/** + * @brief append a float to the buffer + * @param buf buffer + * @param size buffer size + * @param pos current position + * @param val float to append + * @param precision number of decimal places (-1 for default of 6) + */ +static void append_float(char *buf, size_t size, size_t *pos, double val, int precision) +{ + int int_part = (int)val; + double frac = val - int_part; + + if (val < 0) { + append_char(buf, size, pos, '-'); + int_part = -int_part; + frac = -frac; + } + + append_int(buf, size, pos, int_part, 0, false); + append_char(buf, size, pos, '.'); + + int prec = (precision >= 0) ? precision : 6; + for (int i = 0; i < prec; i++) { + frac *= 10; + int d = (int)frac; + append_char(buf, size, pos, '0' + d); + frac -= d; + } +} + +/** + * @brief format a string, a simple version of vsnprintf (with width alignment support) + * @param buf buffer + * @param size buffer size + * @param fmt format string + * @param ap argument list + * @return number of characters written + */ +int sgl_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap) +{ + size_t pos = 0; + + while (*fmt) { + char c = *fmt; + + if (c != '%') { + append_char(buf, size, &pos, c); + fmt++; + continue; + } + + fmt++; + bool left_align = false; + int width = 0; + int precision = -1; + + if (*fmt == '-') { + left_align = true; + fmt++; + } + + while (*fmt >= '0' && *fmt <= '9') { + width = width * 10 + (*fmt - '0'); + fmt++; + } + + if (*fmt == '.') { + fmt++; + precision = 0; + while (*fmt >= '0' && *fmt <= '9') { + precision = precision * 10 + (*fmt - '0'); + fmt++; + } + } + + char spec = *fmt; + switch (spec) { + case 's': { + const char *s = va_arg(ap, const char*); + append_str(buf, size, &pos, s); + break; + } + + case 'd': { + int d = va_arg(ap, int); + append_int(buf, size, &pos, d, width, left_align); + break; + } + + case 'x': { + unsigned int x = va_arg(ap, unsigned int); + append_hex(buf, size, &pos, x, false); + break; + } + + case 'X': { + unsigned int x = va_arg(ap, unsigned int); + append_hex(buf, size, &pos, x, true); + break; + } + + case 'f': { + double f = va_arg(ap, double); + append_float(buf, size, &pos, f, precision); + break; + } + + case 'c': { + char ch = (char)va_arg(ap, int); + append_char(buf, size, &pos, ch); + break; + } + + case '%': { + append_char(buf, size, &pos, '%'); + break; + } + + default: + append_char(buf, size, &pos, '%'); + append_char(buf, size, &pos, spec); + break; + } + + fmt++; + } + + if (size > 0) { + buf[(pos < size) ? pos : (size - 1)] = '\0'; + } + + return (int)pos; +} + +/** + * @brief format a string, a simple version of snprintf (with width alignment support) + * @param buf buffer + * @param size buffer size + * @param fmt format string + * @param ... arguments + * @return number of characters written + */ +int sgl_snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int ret = sgl_vsnprintf(buf, size, fmt, ap); + va_end(ap); + return ret; +} diff --git a/User/system/sgl/draw/build.cmake b/User/system/sgl/draw/build.cmake new file mode 100644 index 0000000..32682f6 --- /dev/null +++ b/User/system/sgl/draw/build.cmake @@ -0,0 +1,34 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_line.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_rect.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_circle.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_arc.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_text.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_ring.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_icon.c + ${CMAKE_CURRENT_LIST_DIR}/sgl_draw_xform.c +) diff --git a/User/system/sgl/draw/lm.cfg b/User/system/sgl/draw/lm.cfg new file mode 100644 index 0000000..f37c2a5 --- /dev/null +++ b/User/system/sgl/draw/lm.cfg @@ -0,0 +1,32 @@ +# source/draw/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +SRC += sgl_draw_line.c +SRC += sgl_draw_rect.c +SRC += sgl_draw_circle.c +SRC += sgl_draw_arc.c +SRC += sgl_draw_text.c +SRC += sgl_draw_ring.c +SRC += sgl_draw_icon.c +SRC += sgl_draw_xform.c diff --git a/User/system/sgl/draw/sgl_draw_arc.c b/User/system/sgl/draw/sgl_draw_arc.c new file mode 100644 index 0000000..84ef377 --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_arc.c @@ -0,0 +1,244 @@ +/* source/draw/sgl_draw_arc.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + + +typedef struct sgl_arc_dot +{ + int16_t cx; + int16_t cy; + int16_t r; + uint32_t r2; + uint16_t rmax; + uint16_t outer; +} sgl_arc_dot_t; + + +static void arc_dot_sin_cos(int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_arc_dot_t *dot,int sin, int cos) +{ + int len = (radius_out + radius_in) / 2; + int r = (radius_out - radius_in) / 2; + if (unlikely(r == 0)) { + return; + } + + if (sin < 0) { + dot->cx = (sin * len - 16348) / 32768; + } + else { + dot->cx = (sin * len + 16348) / 32768; + } + if (cos<0) { + dot->cy = (cos * len - 16348) / 32768; + } + else { + dot->cy = (cos * len + 16348) / 32768; + } + + dot->cx = cx - dot->cx; + dot->cy = cy - dot->cy; + dot->r = r + 1; + dot->r2 = sgl_pow2(r); + dot->rmax = sgl_pow2(r + 1); + dot->outer = 0; +} + + +static inline uint8_t arc_get_dot(sgl_arc_dot_t *dot,int ax, int ay) +{ + uint32_t temp; + uint8_t alpha = SGL_ALPHA_MIN, max = SGL_ALPHA_MIN; + sgl_arc_dot_t *p = dot; + int32_t rate = (0xff00) / (dot->rmax - dot->r2); + + for (int k = 0; k < 2; k++, p++) { + int x = ax > p->cx ? ax - p->cx : p->cx-ax; + int y = ay > p->cy ? ay - p->cy : p->cy-ay; + + if ((x < p->r) && (y < p->r)) { + temp = sgl_pow2(x) + sgl_pow2(y); + if (temp >= p->rmax) { + alpha = 0; + } + else if (temp > p->r2) { + if(dot->outer==0) { + dot->outer = rate; + } + alpha = (p->rmax - temp) * dot->outer >> 8; + } + else { + alpha = SGL_ALPHA_MAX; + } + max = sgl_max(max, alpha); + } + } + return max; +} + + +/** + * @brief draw an arc with alpha + * @param surf pointer to surface + * @param area pointer to area + * @param desc pointer to arc description + * @return none + */ +void sgl_draw_fill_arc(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_arc_t *desc) +{ + int y2 = 0, real_r2 = 0, edge_alpha = 0; + int in_r2 = sgl_pow2(desc->radius_in); + int out_r2 = sgl_pow2(desc->radius_out); + int inv_inner = 0, inv_outer = 0; + sgl_arc_dot_t arc_dot[2]; + + int in_r2_max = sgl_pow2(desc->radius_in - 1); + int out_r2_max = sgl_pow2(desc->radius_out + 1); + int32_t rate = (0xff00) / (in_r2 - in_r2_max); + int32_t rate2 = (0xff00) / (out_r2_max - out_r2); + + sgl_color_t *buf = NULL, *blend = NULL; + int32_t dx, dy; + uint8_t flag = 0xff, in_range; + int32_t ds = 0, de = 0, sd = 0, ed = 0; + int32_t sx = 0, sy = 0, ex = 0, ey = 0; + sgl_color_t tmp_color; + sgl_area_t clip = SGL_AREA_MAX; + + sgl_surf_clip_area_return(surf, area, &clip); + + sgl_area_t c_rect = { + .x1 = desc->cx - desc->radius_out, + .x2 = desc->cx + desc->radius_out, + .y1 = desc->cy - desc->radius_out, + .y2 = desc->cy + desc->radius_out + }; + + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + if (desc->start_angle != 0 || desc->end_angle != 360) { + flag = (desc->end_angle - desc->start_angle > 180) ? 1 : 0; + sx = sgl_sin(desc->start_angle); + sy = -sgl_cos(desc->start_angle); + ex = sgl_sin(desc->end_angle); + ey = -sgl_cos(desc->end_angle); + + if (desc->mode == SGL_ARC_MODE_NORMAL_SMOOTH || desc->mode == SGL_ARC_MODE_RING_SMOOTH) { + arc_dot_sin_cos(desc->cx, desc->cy, desc->radius_in, desc->radius_out, &arc_dot[0], sx, sy); + arc_dot_sin_cos(desc->cx, desc->cy, desc->radius_in, desc->radius_out, &arc_dot[1], ex, ey); + } + + sx = sx >> 7; + sy = sy >> 7; + ex = ex >> 7; + ey = ey >> 7; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + dy = y - desc->cy; + y2 = sgl_pow2(dy); + blend = buf; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + dx = x - desc->cx; + real_r2 = sgl_pow2(x - desc->cx) + y2; + + if (real_r2 >= out_r2_max) { + if (x > desc->cx) { + blend++; + break; + } + continue; + } + if (real_r2 < in_r2_max) { + if (x < desc->cx) { + blend += ((desc->cx - x) * 2); + x = desc->cx * 2 - x; + } + continue; + } + if (real_r2 < in_r2 ) { + if(inv_inner == 0) { + inv_inner = rate; + } + edge_alpha = (real_r2 - in_r2_max) * inv_inner >> 8; + } + else if (real_r2 > out_r2) { + if(inv_outer == 0) { + inv_outer = rate2; + } + edge_alpha = (out_r2_max - real_r2) * inv_outer >> 8; + } + else { + edge_alpha = SGL_ALPHA_MAX; + } + + tmp_color = desc->color; + if (flag != 255) { + ds = (dx * sy - dy * sx); + de = (dy * ex - dx * ey); + in_range = flag > 0 ? (ds > 0 || de >0) : (ds >= 0 && de >= 0); + if (!in_range) { + + switch (desc->mode) { + case SGL_ARC_MODE_NORMAL: + sd = sgl_xy_has_component(dx,dy, sx, sy) ? sgl_abs(ds) : 256; + ed = sgl_xy_has_component(dx,dy, ex, ey) ? sgl_abs(de) : 256; + dx = sgl_min(sd, ed); + tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, *blend, sgl_min(255 - dx, edge_alpha)) : *blend; + break; + + case SGL_ARC_MODE_RING: + sd = sgl_xy_has_component(dx,dy, sx, sy) ? sgl_abs(ds) : 256; + ed = sgl_xy_has_component(dx,dy, ex, ey) ? sgl_abs(de) : 256; + dx = sgl_min(sd, ed); + tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, desc->bg_color, sgl_min(255 - dx, edge_alpha)) : desc->bg_color; + break; + + case SGL_ARC_MODE_NORMAL_SMOOTH: + dx = arc_get_dot(arc_dot, x, y); + tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, *blend, dx) : desc->color; + break; + + case SGL_ARC_MODE_RING_SMOOTH: + dx = arc_get_dot(arc_dot, x, y); + tmp_color = (dx < SGL_ALPHA_MAX) ? sgl_color_mixer(desc->color, desc->bg_color, dx) : desc->color; + break; + + default: break; + } + } + } + + *blend = desc->alpha == SGL_ALPHA_MAX ? sgl_color_mixer(tmp_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(tmp_color, *blend, edge_alpha), *blend, desc->alpha); + } + buf += surf->w; + } +} diff --git a/User/system/sgl/draw/sgl_draw_circle.c b/User/system/sgl/draw/sgl_draw_circle.c new file mode 100644 index 0000000..065453e --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_circle.c @@ -0,0 +1,299 @@ +/* source/draw/sgl_draw_circle.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + + +/** + * @brief Draw a circle + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param color Color of the circle + * @param alpha Alpha of the circle + * @return none + */ +void sgl_draw_fill_circle(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, uint8_t alpha) +{ + sgl_area_t clip = SGL_AREA_MAX; + sgl_color_t *buf = NULL, *blend = NULL; + + sgl_surf_clip_area_return(surf, area, &clip); + + sgl_area_t c_rect = { + .x1 = cx - radius, + .x2 = cx + radius, + .y1 = cy - radius, + .y2 = cy + radius + }; + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + int y2 = 0, real_r2 = 0, edge_alpha = 0; + int r2 = sgl_pow2(radius); + int r2_edge = sgl_pow2(radius + 1); + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + y2 = sgl_pow2(y - cy); + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + + if (real_r2 >= r2_edge) { + if(x > cx) + break; + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(color, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + } + buf += surf->w; + } +} + +#if (!CONFIG_SGL_PIXMAP_BILINEAR_INTERP) +/** + * @brief Draw a circle with pixmap and alpha + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param pixmap Pixmap of image + * @param alpha Alpha of the circle + * @return none + */ +void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha) +{ + int y2 = 0, real_r2 = 0, s_x = cx - radius, s_y = cy - radius; + int r2 = radius * radius; + int r2_max = (radius + 1) * (radius + 1); + sgl_color_t *buf = NULL, *pbuf = NULL, *blend = NULL; + sgl_area_t clip = SGL_AREA_MAX; + uint8_t edge_alpha = 0; + + sgl_surf_clip_area_return(surf, area, &clip); + + sgl_area_t c_rect = { + .x1 = cx - radius, + .x2 = cx + radius, + .y1 = cy - radius, + .y2 = cy + radius + }; + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + uint32_t scale_x = (pixmap->width << SGL_FIXED_SHIFT) / (radius * 2); + uint32_t scale_y = (pixmap->height << SGL_FIXED_SHIFT) / (radius * 2); + uint32_t step_x = 0, step_y = 0; + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + y2 = sgl_pow2(y - cy); + step_y = (scale_y * (y - s_y)) >> SGL_FIXED_SHIFT; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + + step_x = (scale_x * (x - s_x)) >> SGL_FIXED_SHIFT; + pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y); + + if (real_r2 >= r2_max) { + if(x > cx) + break; + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(*pbuf, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(*pbuf, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha)); + } + } + buf += surf->w; + } +} +#else +void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha) +{ + int y2 = 0, real_r2 = 0, s_x = cx - radius, s_y = cy - radius; + int r2 = radius * radius; + int r2_max = (radius + 1) * (radius + 1); + sgl_color_t *buf = NULL, *blend = NULL, ip_color, *pix = (sgl_color_t *)pixmap->bitmap.array; + sgl_area_t clip = SGL_AREA_MAX; + uint8_t edge_alpha = 0; + int fx = 0, fy = 0; + + sgl_surf_clip_area_return(surf, area, &clip); + + sgl_area_t c_rect = { + .x1 = cx - radius, + .x2 = cx + radius, + .y1 = cy - radius, + .y2 = cy + radius + }; + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + const int32_t scale_x = ((int32_t)pixmap->width << SGL_FIXED_SHIFT) / (radius * 2); + const int32_t scale_y = ((int32_t)pixmap->height << SGL_FIXED_SHIFT) / (radius * 2); + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + y2 = sgl_pow2(y - cy); + fy = (int32_t)(y - s_y) * scale_y; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + + fx = (int32_t)(x - s_x) * scale_x; + ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy); + + if (real_r2 >= r2_max) { + if(x > cx) + break; + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(ip_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(ip_color, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? ip_color : sgl_color_mixer(ip_color, *blend, alpha)); + } + } + buf += surf->w; + } +} +#endif // CONFIG_SGL_PIXMAP_BILINEAR_INTERP + +/** + * @brief Draw a circle with alpha and border + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param color Color of the circle + * @param border_color Color of the border + * @param border_width Width of the border + * @param alpha Alpha of the circle + * @return none + */ +void sgl_draw_fill_circle_with_border(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, sgl_color_t border_color, int16_t border_width, uint8_t alpha) +{ + int radius_in = sgl_max(radius - border_width + 1, 0); + int y2 = 0, real_r2 = 0; + int in_r2 = sgl_pow2(radius_in); + int out_r2 = sgl_pow2(radius); + sgl_color_t *buf = NULL, *blend = NULL; + + int in_r2_max = sgl_pow2(radius_in - 1); + int out_r2_max = sgl_pow2(radius + 1); + uint8_t edge_alpha = 0; + sgl_area_t clip = SGL_AREA_MAX; + + sgl_surf_clip_area_return(surf, area, &clip); + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + y2 = sgl_pow2(y - cy); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + + if (real_r2 >= out_r2_max) { + if (x > cx) + break; + continue; + } + if (real_r2 < in_r2_max) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + continue; + } + if (real_r2 < in_r2 ) { + edge_alpha = sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, color, sgl_sqrt_error(real_r2)) : sgl_color_mixer(sgl_color_mixer(border_color, color, edge_alpha), *blend, alpha)); + } + else if (real_r2 > out_r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha)); + } + } + buf += surf->w; + } +} + + +/** + * @brief draw task, the task contains the draw information and canvas + * @param surf surface pointer + * @param area the area of the task + * @param desc the draw information + * @return none + */ +void sgl_draw_circle(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_circle_t *desc) +{ + sgl_color_t color = desc->color; + int16_t radius = desc->radius; + uint8_t alpha = desc->alpha; + uint16_t border = desc->border; + sgl_color_t border_color = desc->border_color; + + if (unlikely(desc->alpha == SGL_ALPHA_MIN)) { + return; + } + + if (desc->pixmap == NULL) { + if (border) { + sgl_draw_fill_circle_with_border(surf, area, desc->cx, desc->cy, radius, color, border_color, border, alpha); + } + else { + sgl_draw_fill_circle(surf, area, desc->cx, desc->cy, radius, color, alpha); + } + } + else { + sgl_draw_fill_circle_pixmap(surf, area, desc->cx, desc->cy, radius, desc->pixmap, alpha); + } +} diff --git a/User/system/sgl/draw/sgl_draw_icon.c b/User/system/sgl/draw/sgl_draw_icon.c new file mode 100644 index 0000000..9f00f39 --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_icon.c @@ -0,0 +1,79 @@ +/* source/draw/sgl_draw_icon.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + + +/** + * @brief draw icon with alpha + * @param surf surface + * @param area area of icon + * @param coords coords of icon + * @param alpha alpha of icon + * @param icon icon pixmap + * @return none + * @note This function is only for 4bpp icon bitmap + */ +void sgl_draw_icon( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, sgl_color_t color, uint8_t alpha, const sgl_icon_pixmap_t *icon) +{ + const uint8_t *dot = icon->bitmap; + sgl_area_t clip = SGL_AREA_MAX; + sgl_color_t *buf = NULL; + int rel_x, rel_y, byte_x, dot_index; + uint8_t alpha_dot; + + sgl_area_t icon_rect = { + .x1 = x, + .x2 = x + icon->width - 1, + .y1 = y, + .y2 = y + icon->height - 1, + }; + + if (!sgl_surf_clip(surf, &icon_rect, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, area)) { + return; + } + + for (int y = clip.y1; y <= clip.y2; y++) { + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, y - surf->y1); + rel_y = y - icon_rect.y1; + + for (int x = clip.x1; x <= clip.x2; x++) { + rel_x = x - icon_rect.x1; + + byte_x = rel_x >> 1; + dot_index = byte_x + (rel_y * (icon->width >> 1)); + alpha_dot = (rel_x & 1) ? dot[dot_index] & 0xF : (dot[dot_index] >> 4); + alpha_dot = alpha_dot | (alpha_dot << 4); + *buf = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *buf, alpha_dot) : sgl_color_mixer(sgl_color_mixer(color, *buf, alpha_dot), *buf, alpha)); + buf++; + } + } +} diff --git a/User/system/sgl/draw/sgl_draw_line.c b/User/system/sgl/draw/sgl_draw_line.c new file mode 100644 index 0000000..c1fa6fa --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_line.c @@ -0,0 +1,195 @@ +/* source/draw/sgl_draw_line.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * @brief draw a horizontal line with alpha + * @param surf surface + * @param area area that contains the line + * @param y line y position + * @param x1 line start x position + * @param x2 line end x position + * @param color line color + * @param alpha alpha of color + * @return none + */ +void sgl_draw_fill_hline(sgl_surf_t *surf, sgl_area_t *area, int16_t y, int16_t x1, int16_t x2, uint8_t width, sgl_color_t color, uint8_t alpha) +{ + sgl_color_t *buf = NULL, *blend = NULL; + sgl_area_t c_rect = {.x1 = x1, .x2 = x2, .y1 = y - (width - 1) / 2, .y2 = y + width / 2}, clip = SGL_AREA_MAX; + + if (c_rect.x1 > c_rect.x2) { + sgl_swap(&c_rect.x1, &c_rect.x2); + } + + sgl_surf_clip_area_return(surf, area, &clip); + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + *blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha); + } + buf += surf->w; + } +} + + +/** + * @brief draw a vertical line with alpha + * @param surf surface + * @param area area that contains the line + * @param x x coordinate + * @param y1 y1 coordinate + * @param y2 y2 coordinate + * @param color line color + * @param alpha alpha of color + * @return none + */ +void sgl_draw_fill_vline(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y1, int16_t y2, uint8_t width, sgl_color_t color, uint8_t alpha) +{ + sgl_color_t *buf = NULL, *blend = NULL; + sgl_area_t c_rect = {.x1 = x - (width - 1) / 2, .x2 = x + width / 2, .y1 = y1,.y2 = y2}, clip = SGL_AREA_MAX; + + if (c_rect.y1 > c_rect.y2) { + sgl_swap(&c_rect.y1, &c_rect.y2); + } + + sgl_surf_clip_area_return(surf, area, &clip); + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + buf += surf->w; + } +} + +/** + * SDF draw anti-aliased line + * @param thickness line thickness (in pixels) + */ +static int32_t sgl_capsule_sdf_optimized(int16_t px, int16_t py, int16_t ax, int16_t ay, int16_t bx, int16_t by) +{ + int64_t pax = px - ax, pay = py - ay, bax = bx - ax, bay = by - ay; + int64_t b_sqd = bax * bax + bay * bay; + int64_t h = (sgl_max(sgl_min((pax * bax + pay * bay), b_sqd), 0)) << 8; + int64_t dx = (pax << 8) - bax * h / b_sqd; + int64_t dy = (pay << 8) - bay * h / b_sqd; + + return sgl_sqrt(dx * dx + dy * dy); +} + + +/** + * @brief draw a slanted line with alpha + * @param surf surface + * @param area area that contains the line + * @param x1 line start x position + * @param y1 line start y position + * @param x2 line end x position + * @param y2 line end y position + * @param thickness line width + * @param color line color + * @param alpha alpha of color + * @return none + * @note This algorithm is SDF algorithm + */ +void draw_line_fill_slanted(sgl_surf_t *surf, sgl_area_t *area, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t thickness, sgl_color_t color, uint8_t alpha) +{ + uint8_t c; + int64_t len; + sgl_area_t clip = SGL_AREA_MAX; + sgl_color_t *buf = NULL, *blend = NULL; + int16_t thick_half = (thickness >> 1); + + sgl_area_t c_rect = { + .x1 = (x1 < x2 ? x1 : x2) - thick_half, + .x2 = (x1 > x2 ? x1 : x2) + thick_half, + .y1 = (y1 < y2 ? y1 : y2) - thick_half, + .y2 = (y1 > y2 ? y1 : y2) + thick_half, + }; + + sgl_surf_clip_area_return(surf, area, &clip); + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + len = sgl_capsule_sdf_optimized(x, y, x1, y1, x2, y2); + + if (len <= (thick_half - 1) << 8) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + continue; + } + + if (len > ((thick_half - 1) << 8) && len < (thick_half << 8)) { + c = len - ((thick_half - 1) << 8); + + if (alpha == SGL_ALPHA_MAX) + *blend = sgl_color_mixer(*blend, color, c); + else + *blend = sgl_color_mixer(sgl_color_mixer(*blend, color, c), *blend, alpha); + } + } + buf += surf->w; + } +} + + +/** + * @brief draw a line + * @param surf surface + * @param area area that contains the line + * @param desc line description + * @return none + */ +void sgl_draw_line(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_line_t *desc) +{ + if (desc->x1 == desc->x2) { + sgl_draw_fill_vline(surf, area, desc->x1, desc->y1, desc->y2, desc->width / 2, desc->color, desc->alpha); + } + else if (desc->y1 == desc->y2) { + sgl_draw_fill_hline(surf, area, desc->y1, desc->x1, desc->x2, desc->width / 2, desc->color, desc->alpha); + } + else { + draw_line_fill_slanted(surf, area, desc->x1, desc->y1, desc->x2, desc->y2, desc->width, desc->color, desc->alpha); + } +} diff --git a/User/system/sgl/draw/sgl_draw_rect.c b/User/system/sgl/draw/sgl_draw_rect.c new file mode 100644 index 0000000..6078ce1 --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_rect.c @@ -0,0 +1,454 @@ +/* source/draw/sgl_draw_rect.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#include +#include +#include + + +/** + * @brief fill a round rectangle with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param color color of rectangle + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, uint8_t alpha) +{ + sgl_area_t clip; + sgl_color_t *buf = NULL, *blend = NULL; + uint8_t edge_alpha = 0; + int cx1 = rect->x1 + radius; + int cx2 = rect->x2 - radius; + int cy1 = rect->y1 + radius; + int cy2 = rect->y2 - radius; + int cx_tmp = 0; + int cy_tmp = 0; + + if (!sgl_surf_clip(surf, area, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, rect)) { + return; + } + + int y2 = 0, real_r2 = 0; + int r2 = sgl_pow2(radius); + int r2_edge = sgl_pow2(radius + 1); + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + if (radius == 0) { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + *blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha); + } + buf += surf->w; + } + } + else { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + if (y > cy1 && y < cy2) { + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + } + else { + cy_tmp = y > cy1 ? cy2 : cy1; + y2 = sgl_pow2(y - cy_tmp); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + if (x > cx1 && x < cx2) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + else { + cx_tmp = x > cx1 ? cx2 : cx1; + real_r2 = sgl_pow2(x - cx_tmp) + y2; + if (real_r2 >= r2_edge) { + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(color, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + } + } + } + buf += surf->w; + } + } +} + + +#include +/** + * @brief fill a round rectangle with alpha and border + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param color color of rectangle + * @param border_color color of border + * @param border_width width of border + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect_with_border(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, sgl_color_t border_color, uint8_t border_width, uint8_t alpha) +{ + int radius_in = sgl_max(radius - border_width + 1, 0); + int y2 = 0, real_r2 = 0; + int in_r2 = sgl_pow2(radius_in); + int out_r2 = sgl_pow2(radius); + sgl_color_t *buf = NULL, *blend = NULL; + uint8_t edge_alpha = 0; + + int cx1 = rect->x1 + radius; + int cx2 = rect->x2 - radius; + int cy1 = rect->y1 + radius; + int cy2 = rect->y2 - radius; + int cx1i = rect->x1 + border_width; + int cx2i = rect->x2 - border_width; + int cyi1 = rect->y1 + border_width; + int cyi2 = rect->y2 - border_width; + int cx_tmp = 0; + int cy_tmp = 0; + + int in_r2_max = sgl_pow2(radius_in - 1); + int out_r2_max = sgl_pow2(radius + 1); + + sgl_area_t clip; + + if (!sgl_surf_clip(surf, area, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, rect)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + if (radius == 0) { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + if (x >= cx1i && x <= cx2i && y >= cyi1 && y <= cyi2) { + *blend = alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha); + } + else { + *blend = alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha); + } + } + buf += surf->w; + } + } + else { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + if (y > cy1 && y < cy2) { + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + if (x < cx1i || x > cx2i) { + *blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? color: sgl_color_mixer(color, *blend, alpha)); + } + } + } + else { + cy_tmp = y > cy1 ? cy2 : cy1; + y2 = sgl_pow2(y - cy_tmp); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + if (x >= cx1 && x <= cx2) { + if (y < cyi1 || y > cyi2) { + *blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + } + } + else { + cx_tmp = x > cx1 ? cx2 : cx1; + real_r2 = sgl_pow2(x - cx_tmp) + y2; + + if (real_r2 >= out_r2_max) { + continue; + } + if (real_r2 < in_r2_max) { + *blend = (alpha == SGL_ALPHA_MAX ? color : sgl_color_mixer(color, *blend, alpha)); + continue; + } + if (real_r2 < in_r2 ) { + edge_alpha = sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, color, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, color, edge_alpha), *blend, alpha)); + } + else if (real_r2 > out_r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(border_color, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(border_color, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? border_color : sgl_color_mixer(border_color, *blend, alpha)); + } + } + } + } + buf += surf->w; + } + } +} + + +#if (!CONFIG_SGL_PIXMAP_BILINEAR_INTERP) +/** + * @brief fill a round rectangle pixmap with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param pixmap pixmap of rectangle + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha) +{ + sgl_area_t clip; + sgl_color_t *buf = NULL, *blend = NULL; + sgl_color_t *pbuf = NULL; + uint8_t edge_alpha = 0; + int cx1 = rect->x1 + radius; + int cx2 = rect->x2 - radius; + int cy1 = rect->y1 + radius; + int cy2 = rect->y2 - radius; + int cx_tmp = 0; + int cy_tmp = 0; + + if (!sgl_surf_clip(surf, area, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, rect)) { + return; + } + + int y2 = 0, real_r2 = 0; + int r2 = sgl_pow2(radius); + int r2_edge = sgl_pow2(radius + 1); + uint32_t scale_x = ((pixmap->width << SGL_FIXED_SHIFT) / (rect->x2 - rect->x1 + 1)); + uint32_t scale_y = ((pixmap->height << SGL_FIXED_SHIFT) / (rect->y2 - rect->y1 + 1)); + uint32_t step_x = 0, step_y = 0; + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + if (radius == 0) { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + step_y = (scale_y * (y - rect->y1)) >> SGL_FIXED_SHIFT; + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT; + pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y); + *blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha)); + } + buf += surf->w; + } + } + else { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + step_y = (scale_y * (y - rect->y1)) >> SGL_FIXED_SHIFT; + if (y > cy1 && y < cy2) { + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT; + pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y); + *blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha)); + } + } + else { + cy_tmp = y > cy1 ? cy2 : cy1; + y2 = sgl_pow2(y - cy_tmp); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + step_x = (scale_x * (x - rect->x1)) >> SGL_FIXED_SHIFT; + pbuf = sgl_pixmap_get_buf(pixmap, step_x, step_y); + + if (x > cx1 && x < cx2) { + *blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha)); + } + else { + cx_tmp = x > cx1 ? cx2 : cx1; + real_r2 = sgl_pow2(x - cx_tmp) + y2; + if (real_r2 >= r2_edge) { + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX ? sgl_color_mixer(*pbuf, *blend, edge_alpha) : sgl_color_mixer(sgl_color_mixer(*pbuf, *blend, edge_alpha), *blend, alpha)); + } + else { + *blend = (alpha == SGL_ALPHA_MAX ? *pbuf : sgl_color_mixer(*pbuf, *blend, alpha)); + } + } + } + } + buf += surf->w; + } + } +} + +#else +/** + * @brief fill a round rectangle pixmap with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param pixmap pixmap of rectangle + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha) +{ + sgl_area_t clip; + sgl_color_t *buf = NULL, *blend = NULL, *pix = (sgl_color_t *)pixmap->bitmap.array; + sgl_color_t ip_color; + uint8_t edge_alpha = 0; + int cx1 = rect->x1 + radius; + int cx2 = rect->x2 - radius; + int cy1 = rect->y1 + radius; + int cy2 = rect->y2 - radius; + int cx_tmp = 0, fx = 0; + int cy_tmp = 0, fy = 0; + + if (!sgl_surf_clip(surf, area, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, rect)) { + return; + } + + int y2 = 0, real_r2 = 0; + int r2 = sgl_pow2(radius); + int r2_edge = sgl_pow2(radius + 1); + + const int32_t rect_w = rect->x2 - rect->x1 + 1; + const int32_t rect_h = rect->y2 - rect->y1 + 1; + const int32_t scale_x = ((int32_t)pixmap->width << SGL_FIXED_SHIFT) / rect_w; + const int32_t scale_y = ((int32_t)pixmap->height << SGL_FIXED_SHIFT) / rect_h; + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + + if (radius == 0) { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + fy = (int32_t)(y - rect->y1) * scale_y; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + fx = (int32_t)(x - rect->x1) * scale_x; + ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy); + *blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha); + } + buf += surf->w; + } + } + else { + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + fy = (int32_t)(y - rect->y1) * scale_y; + + if (y > cy1 && y < cy2) { + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + fx = (int32_t)(x - rect->x1) * scale_x; + ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy); + *blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha); + } + } + else { + cy_tmp = y > cy1 ? cy2 : cy1; + y2 = sgl_pow2(y - cy_tmp); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + fx = (int32_t)(x - rect->x1) * scale_x; + ip_color = sgl_draw_biln_color(pix, pixmap->width, pixmap->height, fx, fy); + + if (x > cx1 && x < cx2) { + *blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha); + } + else { + cx_tmp = x > cx1 ? cx2 : cx1; + real_r2 = sgl_pow2(x - cx_tmp) + y2; + if (real_r2 >= r2_edge) { + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + *blend = (alpha == SGL_ALPHA_MAX) ? sgl_color_mixer(ip_color, *blend, edge_alpha) : + sgl_color_mixer(sgl_color_mixer(ip_color, *blend, edge_alpha), *blend, alpha); + } + else { + *blend = (alpha == SGL_ALPHA_MAX) ? ip_color : sgl_color_mixer(ip_color, *blend, alpha); + } + } + } + } + buf += surf->w; + } + } +} +#endif + + +/** + * @brief fill a round rectangle with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param desc rectangle description + * @return none + */ +void sgl_draw_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *rect, sgl_draw_rect_t *desc) +{ + if (unlikely(desc->alpha == SGL_ALPHA_MIN)) { + return; + } + + if (desc->pixmap == NULL) { + if (desc->border == 0) { + sgl_draw_fill_rect(surf, area, rect, desc->radius, desc->color, desc->alpha); + } + else { + sgl_draw_fill_rect_with_border(surf, area, rect, desc->radius, desc->color, desc->border_color, desc->border, desc->alpha); + } + } + else { + sgl_draw_fill_rect_pixmap(surf, area, rect, desc->radius, desc->pixmap, desc->alpha); + } +} diff --git a/User/system/sgl/draw/sgl_draw_ring.c b/User/system/sgl/draw/sgl_draw_ring.c new file mode 100644 index 0000000..a3351da --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_ring.c @@ -0,0 +1,110 @@ +/* source/draw/sgl_draw_ring.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + + +/** + * @brief draw a ring on surface with alpha + * @param surf: pointer of surface + * @param area: pointer of area + * @param cx: ring center x + * @param cy: ring center y + * @param radius_in: ring inner radius + * @param radius_out: ring outer radius + * @param color: ring color + * @param alpha: ring alpha + * @return none + */ +void sgl_draw_fill_ring(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_color_t color, uint8_t alpha) +{ + int y2 = 0, real_r2 = 0, edge_alpha = 0; + int in_r2 = sgl_pow2(radius_in); + int out_r2 = sgl_pow2(radius_out); + + int in_r2_max = sgl_pow2(radius_in - 1); + int out_r2_max = sgl_pow2(radius_out + 1); + sgl_color_t *buf = NULL, *blend = NULL; + sgl_area_t clip; + + if (unlikely(alpha == SGL_ALPHA_MIN)) { + return; + } + + if (!sgl_surf_clip(surf, area, &clip)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + y2 = sgl_pow2(y - cy); + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + + if (real_r2 >= out_r2_max) { + if (x > cx) break; + continue; + } + if (real_r2 < in_r2_max) { + if (x < cx) { + blend += ((cx - x) * 2); + x = cx*2 - x; + } + continue; + } + + if (alpha == SGL_ALPHA_MAX) { + if (real_r2 < in_r2 ) { + *blend = sgl_color_mixer(color, *blend, sgl_sqrt_error(real_r2)); + } + else if (real_r2 > out_r2) { + *blend = sgl_color_mixer(color, *blend, SGL_ALPHA_MAX - sgl_sqrt_error(real_r2)); + } + else { + *blend = color; + } + } + else { + if (real_r2 < in_r2 ) { + edge_alpha = sgl_sqrt_error(real_r2); + sgl_color_t color_mix = sgl_color_mixer(color, *blend, edge_alpha); + *blend = sgl_color_mixer(color_mix, *blend, alpha); + } + else if (real_r2 > out_r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + sgl_color_t color_mix = sgl_color_mixer(color, *blend, edge_alpha); + *blend = sgl_color_mixer(color_mix, *blend, alpha); + } + else { + *blend = sgl_color_mixer(color, *blend, alpha); + } + } + } + buf += surf->w; + } +} diff --git a/User/system/sgl/draw/sgl_draw_text.c b/User/system/sgl/draw/sgl_draw_text.c new file mode 100644 index 0000000..c254ed0 --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_text.c @@ -0,0 +1,357 @@ +/* source/draw/sgl_draw_text.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + + +#if (CONFIG_SGL_FONT_COMPRESSED) +/** + * @brief RLE state, refrence LVGL + */ +typedef enum { + RLE_STATE_SINGLE = 0, + RLE_STATE_REPEATED, + RLE_STATE_COUNTER, +} sgl_font_rle_state_t; + +/** + * @brief RLE decompress information structure + */ +typedef struct { + uint32_t rdp; + const uint8_t * in; + uint8_t bpp; + uint8_t prev_v; + uint8_t count; + sgl_font_rle_state_t state; +} sgl_font_rle_t; + +static sgl_font_rle_t font_rle = { + .rdp = 0, + .in = NULL, + .bpp = 0, + .prev_v = 0, + .count = 0, + .state = RLE_STATE_SINGLE, +}; + +/** + * @brief Get bits from a byte array + * @param in the byte array + * @param bit_pos the bit position + * @param len the bit length + * @return the bits of a byte + */ +static inline uint8_t get_bits(const uint8_t * in, uint32_t bit_pos, uint8_t len) +{ + uint8_t bit_mask; + switch(len) { + case 1: + bit_mask = 0x1; + break; + case 2: + bit_mask = 0x3; + break; + case 4: + bit_mask = 0xF; + break; + default: + bit_mask = (uint16_t)((uint16_t) 1 << len) - 1; + } + + uint32_t byte_pos = bit_pos >> 3; + bit_pos = bit_pos & 0x7; + + if(bit_pos + len >= 8) { + uint16_t in16 = (in[byte_pos] << 8) + in[byte_pos + 1]; + return (in16 >> (16 - bit_pos - len)) & bit_mask; + } + else { + return (in[byte_pos] >> (8 - bit_pos - len)) & bit_mask; + } +} + +/** + * @brief Decompress a line of RLE data + * @param out the decompressed data + * @param w the width of the decompressed data + * @return none + */ +static inline void decompress_line(uint8_t *out, int32_t w) +{ + int32_t i; + uint8_t v = 0; + uint8_t ret = 0; + sgl_font_rle_t *rle = &font_rle; + + for(i = 0; i < w; i++) { + if(rle->state == RLE_STATE_SINGLE) { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + if(rle->rdp != 0 && rle->prev_v == ret) { + rle->count = 0; + rle->state = RLE_STATE_REPEATED; + } + + rle->prev_v = ret; + rle->rdp += rle->bpp; + } + else if(rle->state == RLE_STATE_REPEATED) { + v = get_bits(rle->in, rle->rdp, 1); + rle->count++; + rle->rdp += 1; + if(v == 1) { + ret = rle->prev_v; + if(rle->count == 11) { + rle->count = get_bits(rle->in, rle->rdp, 6); + rle->rdp += 6; + if(rle->count != 0) { + rle->state = RLE_STATE_COUNTER; + } + else { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; + } + } + } + else { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; + } + } + else if(rle->state == RLE_STATE_COUNTER) { + ret = rle->prev_v; + rle->count--; + if(rle->count == 0) { + ret = get_bits(rle->in, rle->rdp, rle->bpp); + rle->prev_v = ret; + rle->rdp += rle->bpp; + rle->state = RLE_STATE_SINGLE; + } + } + if (out != NULL) { + out[i] = ret; + } + } +} + +/** + * @brief Initialize the RLE decompression state + * @param in Pointer to the input data + * @param bpp Bits per pixel of the input data + * @return none + */ +static inline void font_rle_init(const uint8_t * in, uint8_t bpp) +{ + font_rle.in = in; + font_rle.bpp = bpp; + font_rle.state = RLE_STATE_SINGLE; + font_rle.rdp = 0; + font_rle.prev_v = 0; + font_rle.count = 0; +} +#endif // (!CONFIG_SGL_FONT_COMPRESSED) + + +/** + * @brief Draw a character on the surface with alpha blending + * @param surf Pointer to the surface where the character will be drawn + * @param area Pointer to the area where the character will be drawn + * @param x X coordinate where the character will be drawn + * @param y Y coordinate where the character will be drawn + * @param ch_index Index of the character in the font table + * @param color Foreground color of the character + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @return none + * @note this function is only support bpp:4 + */ +void sgl_draw_character(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, uint32_t ch_index, sgl_color_t color, uint8_t alpha, const sgl_font_t *font) +{ + int offset_y2 = font->font_height - font->table[ch_index].ofs_y - font->base_line; + const uint8_t *dot = &font->bitmap[font->table[ch_index].bitmap_index]; + const uint8_t font_w = font->table[ch_index].box_w; + const uint8_t font_h = font->table[ch_index].box_h; + + uint8_t shift = 0; + uint32_t pixel_index, rel_x, rel_y; + uint16_t byte_index, alpha_dot = 0; + sgl_color_t color_mix, *buf = NULL, *blend = NULL; + sgl_area_t clip; + + sgl_area_t text_rect = { + .x1 = x + font->table[ch_index].ofs_x, + .x2 = x + font->table[ch_index].ofs_x + font_w - 1, + .y1 = y + offset_y2 - font_h, + .y2 = y + offset_y2 - 1, + }; + + if (!sgl_surf_clip(surf, &text_rect, &clip)) { + return; + } + + if (!sgl_area_selfclip(&clip, area)) { + return; + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); +#if (CONFIG_SGL_FONT_COMPRESSED) + if (font->compress == 0) { +#endif // (!CONFIG_SGL_FONT_COMPRESSED == 0) + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + rel_y = y - text_rect.y1; + + for (int x = clip.x1; x <= clip.x2; x++) { + rel_x = x - text_rect.x1; + pixel_index = rel_y * font_w + rel_x; + + if (font->bpp == 4) { + byte_index = pixel_index >> 1; + alpha_dot = sgl_opa4_table[(pixel_index & 1) ? (dot[byte_index] & 0x0F) : (dot[byte_index] >> 4)]; + } + else if (font->bpp == 2) { + byte_index = pixel_index >> 2; + shift = (3 - (pixel_index & 0x3)) * 2; + alpha_dot = sgl_opa2_table[(dot[byte_index] >> shift) & 0x03]; + } + else if (font->bpp == 1) { + byte_index = pixel_index >> 3; + shift = 7 - (pixel_index & 0x7); + alpha_dot = ((dot[byte_index] >> shift) & 0x01) ? SGL_ALPHA_MAX : SGL_ALPHA_MIN; + } + + color_mix = sgl_color_mixer(color, *blend, alpha_dot); + *blend = sgl_color_mixer(color_mix, *blend, alpha); + blend++; + } + buf += surf->w; + } +#if (CONFIG_SGL_FONT_COMPRESSED) + } /* support compressed font */ + else { + uint8_t line_buf[128] = {0}; + font_rle_init(dot, font->bpp); + + for (int y = text_rect.y1; y < clip.y1; y++) { + decompress_line(NULL, font_w); + } + + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + decompress_line(line_buf, font_w); + + for (int x = clip.x1; x <= clip.x2; x++) { + if (font->bpp == 4) { + color_mix = sgl_color_mixer(color, *blend, sgl_opa4_table[line_buf[x - text_rect.x1]]); + } + else if (font->bpp == 2) { + color_mix = sgl_color_mixer(color, *blend, sgl_opa2_table[line_buf[x - text_rect.x1]]); + } + else if (font->bpp == 1) { + color_mix = sgl_color_mixer(color, *blend, line_buf[x - text_rect.x1] ? SGL_ALPHA_MAX : SGL_ALPHA_MIN); + } + *blend = sgl_color_mixer(color_mix, *blend, alpha); + blend++; + } + buf += surf->w; + } + } +#endif +} + + +/** + * @brief Draw a string on the surface with alpha blending + * @param surf Pointer to the surface where the string will be drawn + * @param area Pointer to the area where the string will be drawn + * @param x X coordinate of the top-left corner of the string + * @param y Y coordinate of the top-left corner of the string + * @param str Pointer to the string to be drawn + * @param color Foreground color of the string + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @return none + */ +void sgl_draw_string(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font) +{ + uint32_t ch_index; + uint32_t unicode = 0; + + while (*str) { + str += sgl_utf8_to_unicode(str, &unicode); + ch_index = sgl_search_unicode_ch_index(font, unicode); + sgl_draw_character(surf, area, x, y, ch_index, color, alpha, font); + x += (font->table[ch_index].adv_w >> 4); + } +} + + +/** + * @brief Draw a string on the surface with alpha blending and multiple lines + * @param surf Pointer to the surface where the string will be drawn + * @param area Pointer to the area where the string will be drawn + * @param x X coordinate of the top-left corner of the string + * @param y Y coordinate of the top-left corner of the string + * @param str Pointer to the string to be drawn + * @param color Foreground color of the string + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @param line_margin Margin between lines + * @return none + */ +void sgl_draw_string_mult_line(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font, uint8_t line_margin) +{ + int16_t ch_index, ch_width; + int16_t x_off = x; + uint32_t unicode = 0; + + while (*str) { + if (*str == '\n') { + x_off = x; + y += (font->font_height + line_margin); + str ++; + continue; + } + + str += sgl_utf8_to_unicode(str, &unicode); + ch_index = sgl_search_unicode_ch_index(font, unicode); + + ch_width = (font->table[ch_index].adv_w >> 4); + + if ((x_off + ch_width) > area->x2) { + x_off = x; + y += (font->font_height + line_margin); + } + + sgl_draw_character(surf, area, x_off, y, ch_index, color, alpha, font); + x_off += ch_width; + } +} diff --git a/User/system/sgl/draw/sgl_draw_xform.c b/User/system/sgl/draw/sgl_draw_xform.c new file mode 100644 index 0000000..660eee3 --- /dev/null +++ b/User/system/sgl/draw/sgl_draw_xform.c @@ -0,0 +1,157 @@ +/* source/draw/sgl_draw_xform.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + + +/** + * @brief calculate a point color by bilinear interpolate + * @param buffer point to image pixmap start buffer + * @param w width of buffer + * @param h height of buffer + * @param fx x coordinate of point + * @param fy y coordinate of point + * @return point color + */ +sgl_color_t sgl_draw_biln_color(const sgl_color_t *buffer, int16_t w, int16_t h, int32_t fx, int32_t fy) +{ + sgl_color_t ret; + int32_t max_x = (((int32_t)w) - 1) << SGL_FIXED_SHIFT; + int32_t max_y = (((int32_t)h) - 1) << SGL_FIXED_SHIFT; + fx = fx < 0 ? 0 : (fx > max_x ? max_x : fx); + fy = fy < 0 ? 0 : (fy > max_y ? max_y : fy); + + const int32_t x0 = fx >> SGL_FIXED_SHIFT; + const int32_t y0 = fy >> SGL_FIXED_SHIFT; + const int32_t dx = fx & SGL_FIXED_MASK; + const int32_t dy = fy & SGL_FIXED_MASK; + const int32_t dx1 = SGL_FIXED_ONE - dx; + const int32_t dy1 = SGL_FIXED_ONE - dy; + const int32_t point = (y0 * w) + x0; + + const sgl_color_t p00 = buffer[point]; + const sgl_color_t p01 = buffer[point + 1]; + const sgl_color_t p10 = buffer[point + w]; + const sgl_color_t p11 = buffer[point + w + 1]; + + const uint8_t r00 = p00.ch.red; + const uint8_t r01 = p01.ch.red; + const uint8_t r10 = p10.ch.red; + const uint8_t r11 = p11.ch.red; + + const uint8_t g00 = p00.ch.green; + const uint8_t g01 = p01.ch.green; + const uint8_t g10 = p10.ch.green; + const uint8_t g11 = p11.ch.green; + + const uint8_t b00 = p00.ch.blue; + const uint8_t b01 = p01.ch.blue; + const uint8_t b10 = p10.ch.blue; + const uint8_t b11 = p11.ch.blue; + + ret.ch.red = ((r00 * dx1 * dy1) + (r01 * dx * dy1) + (r10 * dx1 * dy) + (r11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT); + ret.ch.green = ((g00 * dx1 * dy1) + (g01 * dx * dy1) + (g10 * dx1 * dy) + (g11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT); + ret.ch.blue = ((b00 * dx1 * dy1) + (b01 * dx * dy1) + (b10 * dx1 * dy) + (b11 * dx * dy)) >> (2 * SGL_FIXED_SHIFT); + + return ret; +} + + +/** + * @brief transform a surface + * @param dst destination surface + * @param src source surface + * @param area area of surface + * @param x x coordinate of surface + * @param y y coordinate of surface + * @param rotation rotation angle + * @return none + * @note This function has implemented angle normalization to the range of 0 to 360 degrees. + */ +void sgl_draw_xform_surf(sgl_surf_t *dst, sgl_surf_t *src, sgl_area_t *area, int16_t x, int16_t y, int16_t rotation) +{ + const int32_t sin_val = sgl_sin(rotation); + const int32_t cos_val = sgl_cos(rotation); + + const int16_t half_w = src->w / 2; + const int16_t half_h = src->h / 2; + + const int16_t x1r = (cos_val * (-half_w) - sin_val * (-half_h)) / SGL_SIN_FIXED_ONE; + const int16_t y1r = (sin_val * (-half_w) + cos_val * (-half_h)) / SGL_SIN_FIXED_ONE; + + const int16_t x2r = (cos_val * half_w - sin_val * (-half_h)) / SGL_SIN_FIXED_ONE; + const int16_t y2r = (sin_val * half_w + cos_val * (-half_h)) / SGL_SIN_FIXED_ONE; + + const int16_t x3r = (cos_val * half_w - sin_val * half_h) / SGL_SIN_FIXED_ONE; + const int16_t y3r = (sin_val * half_w + cos_val * half_h) / SGL_SIN_FIXED_ONE; + + const int16_t x4r = (cos_val * (-half_w) - sin_val * half_h) / SGL_SIN_FIXED_ONE; + const int16_t y4r = (sin_val * (-half_w) + cos_val * half_h) / SGL_SIN_FIXED_ONE; + + const int16_t min_x = sgl_min4(x1r, x2r, x3r, x4r); + const int16_t min_y = sgl_min4(y1r, y2r, y3r, y4r); + const int16_t max_x = sgl_max4(x1r, x2r, x3r, x4r); + const int16_t max_y = sgl_max4(y1r, y2r, y3r, y4r); + + const int16_t center_x = x + half_w; + const int16_t center_y = y + half_h; + + const int16_t buf_width = src->w > 0 ? src->w : 1; + const int16_t buf_height = src->h > 0 ? src->h : 1; + const int16_t buf_size = buf_width * buf_height; + + if (buf_size <= 0 || src->w <= 0) { + return; + } + + for (int py = (int)min_y; py <= max_y; py++) { + for (int px = (int)min_x; px <= max_x; px++) { + int rel_x = px; + int rel_y = py; + + int32_t orig_x_fixed = cos_val * rel_x + sin_val * rel_y; + int32_t orig_y_fixed = -sin_val * rel_x + cos_val * rel_y; + + const int orig_x = (orig_x_fixed / SGL_SIN_FIXED_ONE) + half_w; + const int orig_y = (orig_y_fixed / SGL_SIN_FIXED_ONE) + half_h; + + if (orig_x >= 0 && orig_x < buf_width && orig_y >= 0 && orig_y < buf_height) { + int src_idx = orig_y * buf_width + orig_x; + const int dst_x = center_x + px; + const int dst_y = center_y + py; + + if (dst_x >= area->x1 && dst_x <= area->x2 && dst_y >= area->y1 && dst_y <= area->y2 + && dst_x >= dst->x1 && dst_x <= dst->x2 && dst_y >= dst->y1 && dst_y <= dst->y2 + ) { + int dst_idx = (dst_y - dst->y1) * dst->w + (dst_x - dst->x1); + dst->buffer[dst_idx] = src->buffer[src_idx]; + } + } + } + } +} diff --git a/User/system/sgl/fonts/build.cmake b/User/system/sgl/fonts/build.cmake new file mode 100644 index 0000000..c371396 --- /dev/null +++ b/User/system/sgl/fonts/build.cmake @@ -0,0 +1,64 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +if(SGL_FONT_SONG23) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_song23.c + ) +endif() + +if(SGL_FONT_CONSOLAS14) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas14.c + ) +endif() + +if(SGL_FONT_CONSOLAS23) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas23.c + ) +endif() + +if(SGL_FONT_CONSOLAS24) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas24.c + ) +endif() + +if(SGL_FONT_CONSOLAS32) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas34.c + ) +endif() + +if(CONFIG_SGL_FONT_CONSOLAS24_COMPRESS) + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/sgl_ascii_consolas24_compress.c + ) +endif() diff --git a/User/system/sgl/fonts/lm.cfg b/User/system/sgl/fonts/lm.cfg new file mode 100644 index 0000000..a19ab1e --- /dev/null +++ b/User/system/sgl/fonts/lm.cfg @@ -0,0 +1,55 @@ +# source/fonts/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +CONFIG_SGL_FONT_SONG23 + choices = n, y + default = n + +CONFIG_SGL_FONT_CONSOLAS14 + choices = n, y + default = n + +CONFIG_SGL_FONT_CONSOLAS23 + choices = n, y + default = n + +CONFIG_SGL_FONT_CONSOLAS24 + choices = n, y + default = n + +CONFIG_SGL_FONT_CONSOLAS32 + choices = n, y + default = n + +CONFIG_SGL_FONT_CONSOLAS24_COMPRESS + choices = n, y + default = n + depends = CONFIG_SGL_FONT_COMPRESSED + +SRC-$(CONFIG_SGL_FONT_SONG23) += sgl_ascii_song23.c +SRC-$(CONFIG_SGL_FONT_CONSOLAS14) += sgl_ascii_consolas14.c +SRC-$(CONFIG_SGL_FONT_CONSOLAS23) += sgl_ascii_consolas23.c +SRC-$(CONFIG_SGL_FONT_CONSOLAS24) += sgl_ascii_consolas24.c +SRC-$(CONFIG_SGL_FONT_CONSOLAS32) += sgl_ascii_consolas34.c +SRC-$(CONFIG_SGL_FONT_CONSOLAS24_COMPRESS) += sgl_ascii_consolas24_compress.c diff --git a/User/system/sgl/fonts/sgl_ascii_consolas14.c b/User/system/sgl/fonts/sgl_ascii_consolas14.c new file mode 100644 index 0000000..91f42a6 --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_consolas14.c @@ -0,0 +1,662 @@ +/* source/fonts/sgl_ascii_consolas14.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + + +#if (CONFIG_SGL_FONT_CONSOLAS14) + + +static const uint8_t sgl_ascii_consolas14_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0x5e, 0x4, 0xd0, 0x4d, 0x3, 0xc0, 0x3c, 0x2, + 0x90, 0x26, 0x5, 0xe0, + + /* U+0022 "\"" */ + 0x7c, 0x2f, 0x6, 0xb1, 0xf0, 0x47, 0xb, 0x0, + + /* U+0023 "#" */ + 0x0, 0xd0, 0xa3, 0x0, 0x1c, 0xb, 0x20, 0x5d, + 0xec, 0xfc, 0x40, 0x49, 0xd, 0x0, 0x5, 0x70, + 0xd0, 0x9, 0xdd, 0xcf, 0xc0, 0x9, 0x43, 0xa0, + 0x0, 0xa3, 0x49, 0x0, + + /* U+0024 "$" */ + 0x0, 0x1, 0x0, 0x0, 0x9, 0x30, 0x6, 0xdf, + 0xe4, 0x2e, 0x2d, 0x0, 0x3e, 0x1d, 0x0, 0x8, + 0xfd, 0x10, 0x0, 0x5d, 0xe4, 0x0, 0x67, 0x5c, + 0x11, 0x87, 0x9b, 0x4e, 0xff, 0xb1, 0x0, 0xc1, + 0x0, 0x0, 0x40, 0x0, + + /* U+0025 "%" */ + 0x5b, 0xc1, 0xc, 0x2b, 0x39, 0x47, 0x70, 0x3b, + 0x83, 0xc0, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x89, + 0xba, 0x0, 0x3b, 0xa3, 0x94, 0xc, 0x2b, 0x28, + 0x48, 0x60, 0x4c, 0xb0, + + /* U+0026 "&" */ + 0x5, 0xde, 0x60, 0x0, 0xe2, 0x3e, 0x0, 0xd, + 0x46, 0xb0, 0x0, 0x7f, 0xa0, 0x0, 0x3d, 0xac, + 0x1f, 0x9, 0x70, 0xbc, 0xc0, 0x89, 0x1, 0xf9, + 0x1, 0xbd, 0xc8, 0xe3, + + /* U+0027 "'" */ + 0x5e, 0x4d, 0x29, + + /* U+0028 "(" */ + 0x0, 0x7, 0x0, 0xa, 0x80, 0x4, 0xc0, 0x0, + 0xc4, 0x0, 0x1f, 0x0, 0x3, 0xd0, 0x0, 0x2d, + 0x0, 0x0, 0xf1, 0x0, 0xa, 0x60, 0x0, 0x2e, + 0x10, 0x0, 0x6c, 0x0, 0x0, 0x30, + + /* U+0029 ")" */ + 0x25, 0x0, 0x1d, 0x40, 0x3, 0xd0, 0x0, 0xb6, + 0x0, 0x6a, 0x0, 0x3c, 0x0, 0x4c, 0x0, 0x79, + 0x0, 0xc4, 0x5, 0xb0, 0x2d, 0x10, 0x2, 0x0, + + /* U+002A "*" */ + 0x0, 0x1a, 0x0, 0xa, 0x5a, 0x96, 0x0, 0xbf, + 0x50, 0xa, 0x5a, 0x95, 0x0, 0x1a, 0x0, + + /* U+002B "+" */ + 0x0, 0x3c, 0x0, 0x0, 0x3, 0xc0, 0x0, 0x7e, + 0xef, 0xee, 0x10, 0x3, 0xc0, 0x0, 0x0, 0x3c, + 0x0, 0x0, 0x2, 0x80, 0x0, + + /* U+002C "," */ + 0x0, 0x0, 0x8, 0xe1, 0x4, 0xf2, 0x4, 0xe0, + 0x7a, 0x20, + + /* U+002D "-" */ + 0x7f, 0xff, 0x0, + + /* U+002E "." */ + 0x7d, 0x18, 0xe1, + + /* U+002F "/" */ + 0x0, 0x0, 0xc, 0x20, 0x0, 0x7, 0x70, 0x0, + 0x3, 0xc0, 0x0, 0x0, 0xc2, 0x0, 0x0, 0x87, + 0x0, 0x0, 0x3b, 0x0, 0x0, 0xc, 0x20, 0x0, + 0x8, 0x60, 0x0, 0x0, + + /* U+0030 "0" */ + 0x3, 0xde, 0xb1, 0x0, 0xe3, 0x9, 0x90, 0x4b, + 0x0, 0x9e, 0x6, 0x91, 0xca, 0xf0, 0x7c, 0xe6, + 0xf, 0x5, 0xe2, 0x2, 0xe0, 0xe, 0x30, 0x98, + 0x0, 0x4d, 0xea, 0x0, + + /* U+0031 "1" */ + 0x1, 0x9f, 0x20, 0xe, 0x7f, 0x20, 0x1, 0xf, + 0x20, 0x0, 0xf, 0x20, 0x0, 0xf, 0x20, 0x0, + 0xf, 0x20, 0x0, 0xf, 0x20, 0xe, 0xff, 0xfc, + + /* U+0032 "2" */ + 0x6, 0xee, 0x90, 0x7, 0x10, 0xd5, 0x0, 0x0, + 0xa7, 0x0, 0x0, 0xe3, 0x0, 0xa, 0x90, 0x0, + 0x9a, 0x0, 0x9, 0xb0, 0x0, 0x2f, 0xff, 0xfe, + + /* U+0033 "3" */ + 0xa, 0xee, 0xa0, 0x0, 0x0, 0xd5, 0x0, 0x1, + 0xd2, 0x1, 0xdf, 0xa0, 0x0, 0x0, 0xb8, 0x0, + 0x0, 0x5b, 0x0, 0x0, 0xb6, 0xe, 0xed, 0x70, + + /* U+0034 "4" */ + 0x0, 0xc, 0xf0, 0x0, 0x7, 0xaf, 0x0, 0x2, + 0xd1, 0xf0, 0x0, 0xb4, 0x1f, 0x0, 0x6a, 0x1, + 0xf0, 0xb, 0xee, 0xef, 0xe3, 0x0, 0x1, 0xf0, + 0x0, 0x0, 0x1f, 0x0, + + /* U+0035 "5" */ + 0xde, 0xee, 0x4d, 0x20, 0x0, 0xd2, 0x0, 0xc, + 0xed, 0x90, 0x0, 0x1b, 0x80, 0x0, 0x6a, 0x0, + 0x1c, 0x5e, 0xed, 0x60, + + /* U+0036 "6" */ + 0x0, 0x7d, 0xe5, 0x8, 0xa1, 0x0, 0xe, 0x0, + 0x0, 0x3e, 0xbc, 0xb2, 0x4d, 0x10, 0x6c, 0x2d, + 0x0, 0x1f, 0xe, 0x30, 0x6b, 0x3, 0xdd, 0xb1, + + /* U+0037 "7" */ + 0x4f, 0xff, 0xfd, 0x0, 0x0, 0x69, 0x0, 0x0, + 0xe2, 0x0, 0x6, 0xb0, 0x0, 0xd, 0x30, 0x0, + 0x5c, 0x0, 0x0, 0xc5, 0x0, 0x4, 0xd0, 0x0, + + /* U+0038 "8" */ + 0x5, 0xdd, 0xc2, 0xf, 0x10, 0x7a, 0xf, 0x30, + 0x89, 0x5, 0xec, 0xb0, 0x8, 0xc8, 0xe4, 0x2e, + 0x0, 0x6d, 0x3e, 0x10, 0x6c, 0x7, 0xdd, 0xc2, + + /* U+0039 "9" */ + 0x5, 0xdd, 0x90, 0x2e, 0x10, 0xa7, 0x5b, 0x0, + 0x4c, 0x3e, 0x10, 0x6d, 0x7, 0xdc, 0xbc, 0x0, + 0x0, 0x69, 0x0, 0x4, 0xe2, 0xd, 0xeb, 0x30, + + /* U+003A ":" */ + 0x6e, 0x14, 0xb0, 0x0, 0x0, 0x0, 0x4b, 0x6, + 0xe1, + + /* U+003B ";" */ + 0x6, 0xe1, 0x4, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0x5, 0xd1, 0x3, 0xf3, 0x3, 0xe1, 0x6b, 0x30, + + /* U+003C "<" */ + 0x0, 0x0, 0x30, 0x0, 0x7, 0xd1, 0x0, 0xab, + 0x0, 0xc, 0x90, 0x0, 0x6, 0xd2, 0x0, 0x0, + 0x3d, 0x40, 0x0, 0x2, 0xc2, 0x0, 0x0, 0x0, + + /* U+003D "=" */ + 0x2d, 0xdd, 0xda, 0x0, 0x0, 0x0, 0x3d, 0xdd, + 0xdb, + + /* U+003E ">" */ + 0x21, 0x0, 0x5, 0xd2, 0x0, 0x3, 0xd4, 0x0, + 0x2, 0xd6, 0x0, 0x6d, 0x20, 0x9b, 0x0, 0x88, + 0x0, 0x0, 0x0, 0x0, + + /* U+003F "?" */ + 0x3e, 0xc4, 0x0, 0x4, 0xe2, 0x0, 0xc, 0x50, + 0x9d, 0xa0, 0x9, 0x50, 0x0, 0x52, 0x0, 0x5, + 0x30, 0x0, 0xc7, 0x0, + + /* U+0040 "@" */ + 0x0, 0x9b, 0xc5, 0x0, 0xb5, 0x0, 0xc1, 0x49, + 0x5c, 0xc7, 0x69, 0x4d, 0x2d, 0x57, 0xd5, 0xa4, + 0xa5, 0x7d, 0x59, 0x88, 0x94, 0xd1, 0xc7, 0xb9, + 0xc, 0x10, 0x0, 0x0, 0x79, 0x0, 0x10, 0x0, + 0x9c, 0xba, 0x0, + + /* U+0041 "A" */ + 0x0, 0x8f, 0x20, 0x0, 0xd, 0xa8, 0x0, 0x3, + 0xc3, 0xd0, 0x0, 0x87, 0xe, 0x20, 0xd, 0x20, + 0x97, 0x2, 0xff, 0xff, 0xc0, 0x78, 0x0, 0xf, + 0x1c, 0x40, 0x0, 0xb6, + + /* U+0042 "B" */ + 0x1f, 0xee, 0xb1, 0x1f, 0x0, 0xa8, 0x1f, 0x0, + 0x7a, 0x1f, 0x0, 0xc5, 0x1f, 0xdf, 0xd2, 0x1f, + 0x0, 0x7d, 0x1f, 0x0, 0x6c, 0x1f, 0xdd, 0xb2, + + /* U+0043 "C" */ + 0x0, 0xae, 0xea, 0xb, 0x90, 0x3, 0x3e, 0x0, + 0x0, 0x5b, 0x0, 0x0, 0x6b, 0x0, 0x0, 0x4e, + 0x0, 0x0, 0xd, 0x80, 0x2, 0x2, 0xbe, 0xe9, + + /* U+0044 "D" */ + 0x5f, 0xed, 0x80, 0x5, 0xb0, 0xb, 0x90, 0x5b, + 0x0, 0x2f, 0x5, 0xb0, 0x0, 0xf2, 0x5b, 0x0, + 0xf, 0x15, 0xb0, 0x2, 0xe0, 0x5b, 0x1, 0xc8, + 0x5, 0xfe, 0xd7, 0x0, + + /* U+0045 "E" */ + 0xde, 0xee, 0x7d, 0x30, 0x0, 0xd3, 0x0, 0xd, + 0x30, 0x0, 0xde, 0xee, 0x5d, 0x30, 0x0, 0xd3, + 0x0, 0xd, 0xee, 0xe7, + + /* U+0046 "F" */ + 0xce, 0xee, 0x7c, 0x40, 0x0, 0xc4, 0x0, 0xc, + 0x40, 0x0, 0xce, 0xee, 0x4c, 0x40, 0x0, 0xc4, + 0x0, 0xc, 0x40, 0x0, + + /* U+0047 "G" */ + 0x1, 0xae, 0xfa, 0xd, 0x80, 0x4, 0x5c, 0x0, + 0x0, 0x98, 0x0, 0x0, 0x88, 0x9, 0xdd, 0x6b, + 0x0, 0x1f, 0xe, 0x60, 0x1f, 0x2, 0xbe, 0xea, + + /* U+0048 "H" */ + 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, + 0x1f, 0x5b, 0x0, 0x1f, 0x5f, 0xee, 0xef, 0x5b, + 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, + + /* U+0049 "I" */ + 0xde, 0xfe, 0x80, 0x3d, 0x0, 0x3, 0xd0, 0x0, + 0x3d, 0x0, 0x3, 0xd0, 0x0, 0x3d, 0x0, 0x3, + 0xd0, 0xe, 0xef, 0xe8, + + /* U+004A "J" */ + 0xbe, 0xef, 0x20, 0x0, 0xe2, 0x0, 0xe, 0x20, + 0x0, 0xe2, 0x0, 0xe, 0x20, 0x0, 0xe1, 0x30, + 0x3e, 0xb, 0xed, 0x40, + + /* U+004B "K" */ + 0x1f, 0x0, 0x99, 0x1, 0xf0, 0x5c, 0x0, 0x1f, + 0x2d, 0x10, 0x1, 0xfd, 0x40, 0x0, 0x1f, 0xb8, + 0x0, 0x1, 0xf1, 0xe4, 0x0, 0x1f, 0x4, 0xe1, + 0x1, 0xf0, 0x8, 0xb0, + + /* U+004C "L" */ + 0xa6, 0x0, 0xa, 0x60, 0x0, 0xa6, 0x0, 0xa, + 0x60, 0x0, 0xa6, 0x0, 0xa, 0x60, 0x0, 0xa6, + 0x0, 0xa, 0xee, 0xea, + + /* U+004D "M" */ + 0x5f, 0x10, 0x8f, 0x6, 0xe6, 0xc, 0xe0, 0x79, + 0xc3, 0x9e, 0x8, 0x6c, 0xa4, 0xd1, 0x85, 0x7e, + 0xd, 0x29, 0x51, 0x40, 0xc3, 0xa4, 0x0, 0xc, + 0x3b, 0x40, 0x0, 0xb4, + + /* U+004E "N" */ + 0x4f, 0x40, 0x1e, 0x4e, 0xb0, 0x1e, 0x4a, 0xe2, + 0x1e, 0x4a, 0x79, 0x1e, 0x4a, 0x1e, 0x2e, 0x4a, + 0x9, 0x8e, 0x4a, 0x2, 0xee, 0x4a, 0x0, 0xae, + + /* U+004F "O" */ + 0x4, 0xde, 0xb1, 0x2, 0xe3, 0x8, 0xb0, 0x7a, + 0x0, 0xf, 0x1a, 0x70, 0x0, 0xd3, 0xa7, 0x0, + 0xd, 0x38, 0x90, 0x0, 0xf1, 0x2f, 0x30, 0x9b, + 0x0, 0x5e, 0xea, 0x10, + + /* U+0050 "P" */ + 0x1f, 0xde, 0xb2, 0x1f, 0x0, 0x7b, 0x1f, 0x0, + 0x2e, 0x1f, 0x0, 0x9a, 0x1f, 0xdd, 0x90, 0x1f, + 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, + + /* U+0051 "Q" */ + 0x4, 0xdf, 0xb1, 0x2, 0xe3, 0x8, 0xb0, 0x7a, + 0x0, 0xf, 0x1a, 0x70, 0x0, 0xd3, 0xa7, 0x0, + 0xd, 0x38, 0x90, 0x1, 0xf1, 0x2e, 0x41, 0x9a, + 0x0, 0x5d, 0xf9, 0x0, 0x0, 0x2e, 0x11, 0x10, + 0x0, 0x6d, 0xd4, + + /* U+0052 "R" */ + 0xfe, 0xea, 0x0, 0xf0, 0xc, 0x60, 0xf0, 0x8, + 0x80, 0xf0, 0x1d, 0x40, 0xfd, 0xf7, 0x0, 0xf0, + 0x6c, 0x0, 0xf0, 0xc, 0x50, 0xf0, 0x4, 0xd0, + + /* U+0053 "S" */ + 0x5, 0xde, 0xe4, 0x1e, 0x20, 0x0, 0x2f, 0x10, + 0x0, 0x8, 0xf8, 0x10, 0x0, 0x29, 0xf4, 0x0, + 0x0, 0x6c, 0x11, 0x0, 0x8a, 0x4e, 0xfe, 0xa1, + + /* U+0054 "T" */ + 0x7e, 0xef, 0xee, 0x10, 0x3, 0xd0, 0x0, 0x0, + 0x3d, 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d, + 0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d, 0x0, + 0x0, 0x3, 0xd0, 0x0, + + /* U+0055 "U" */ + 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, + 0x1f, 0x5b, 0x0, 0x1f, 0x5b, 0x0, 0x1f, 0x5b, + 0x0, 0x1e, 0x2e, 0x10, 0x7a, 0x6, 0xdd, 0xb1, + + /* U+0056 "V" */ + 0xd5, 0x0, 0xb, 0x67, 0xa0, 0x0, 0xf1, 0x2f, + 0x0, 0x4c, 0x0, 0xd4, 0x9, 0x60, 0x8, 0x90, + 0xe1, 0x0, 0x3e, 0x3c, 0x0, 0x0, 0xeb, 0x70, + 0x0, 0x9, 0xf2, 0x0, + + /* U+0057 "W" */ + 0xb4, 0x0, 0x9, 0x4a, 0x50, 0x0, 0xa3, 0x96, + 0x3, 0xb, 0x28, 0x75, 0xe0, 0xc1, 0x77, 0xad, + 0x4d, 0x5, 0x9d, 0x59, 0xd0, 0x4d, 0x90, 0xed, + 0x3, 0xf4, 0xb, 0xd0, + + /* U+0058 "X" */ + 0x6d, 0x0, 0x3e, 0x0, 0xc6, 0xc, 0x50, 0x3, + 0xe7, 0xb0, 0x0, 0x9, 0xf2, 0x0, 0x0, 0xbf, + 0x50, 0x0, 0x5d, 0x5e, 0x0, 0xe, 0x40, 0xb8, + 0x9, 0xb0, 0x2, 0xf2, + + /* U+0059 "Y" */ + 0xb8, 0x0, 0xd, 0x53, 0xf1, 0x5, 0xc0, 0xa, + 0x90, 0xd3, 0x0, 0x2f, 0x7b, 0x0, 0x0, 0x9f, + 0x20, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x3d, 0x0, + 0x0, 0x3, 0xd0, 0x0, + + /* U+005A "Z" */ + 0x3f, 0xff, 0xfd, 0x0, 0x0, 0xc6, 0x0, 0x6, + 0xc0, 0x0, 0x1e, 0x30, 0x0, 0xa8, 0x0, 0x4, + 0xd0, 0x0, 0xd, 0x40, 0x0, 0x5f, 0xff, 0xfe, + + /* U+005B "[" */ + 0xfd, 0xbf, 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, + 0x0, 0xf0, 0xf, 0x0, 0xf0, 0xf, 0xdb, + + /* U+005C "\\" */ + 0xd, 0x20, 0x0, 0x6, 0x80, 0x0, 0x0, 0xe0, + 0x0, 0x0, 0x96, 0x0, 0x0, 0x2c, 0x0, 0x0, + 0xb, 0x30, 0x0, 0x5, 0xa0, 0x0, 0x0, 0xd1, + 0x0, 0x0, 0x78, 0x0, 0x0, 0x16, + + /* U+005D "]" */ + 0x4d, 0xe9, 0x0, 0x69, 0x0, 0x69, 0x0, 0x69, + 0x0, 0x69, 0x0, 0x69, 0x0, 0x69, 0x0, 0x69, + 0x0, 0x69, 0x4d, 0xe9, + + /* U+005E "^" */ + 0x0, 0x6e, 0x0, 0x0, 0xc7, 0x80, 0x7, 0x60, + 0xd1, 0x1d, 0x0, 0x5a, + + /* U+005F "_" */ + 0xdd, 0xdd, 0xdd, 0x80, + + /* U+0060 "`" */ + 0xd, 0x10, 0xf0, 0xd, 0x0, + + /* U+0061 "a" */ + 0x8, 0xdd, 0xc1, 0x1, 0x0, 0x88, 0x5, 0xcc, + 0xda, 0x1f, 0x20, 0x6a, 0x2e, 0x1, 0xca, 0x9, + 0xec, 0x9a, + + /* U+0062 "b" */ + 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1e, 0x7d, + 0xd2, 0x1f, 0x80, 0x6b, 0x1f, 0x0, 0x1e, 0x1f, + 0x0, 0x2e, 0x1f, 0x0, 0x89, 0xc, 0xed, 0x90, + + /* U+0063 "c" */ + 0x1, 0xae, 0xe6, 0xa, 0x90, 0x1, 0xf, 0x10, + 0x0, 0xf, 0x10, 0x0, 0xc, 0x80, 0x1, 0x2, + 0xbe, 0xe6, + + /* U+0064 "d" */ + 0x0, 0x0, 0x6a, 0x0, 0x0, 0x6a, 0x3, 0xcd, + 0xea, 0xe, 0x20, 0x6a, 0x4c, 0x0, 0x6a, 0x5b, + 0x0, 0x6a, 0x2e, 0x1, 0xda, 0x8, 0xdb, 0x7a, + + /* U+0065 "e" */ + 0x3, 0xcc, 0xb2, 0xd, 0x10, 0x5b, 0x3f, 0xcc, + 0xcc, 0x4d, 0x0, 0x0, 0x1f, 0x40, 0x0, 0x4, + 0xdd, 0xd7, + + /* U+0066 "f" */ + 0x0, 0x1b, 0xdd, 0x20, 0x8, 0x90, 0x0, 0x0, + 0xa6, 0x0, 0x7, 0xdf, 0xed, 0xd0, 0x0, 0xa6, + 0x0, 0x0, 0xa, 0x60, 0x0, 0x0, 0xa6, 0x0, + 0x0, 0xa, 0x60, 0x0, + + /* U+0067 "g" */ + 0x5, 0xcd, 0xff, 0x10, 0xf1, 0xa, 0x60, 0xe, + 0x20, 0xb5, 0x0, 0xcb, 0xc8, 0x0, 0x2d, 0x0, + 0x0, 0x0, 0xee, 0xed, 0x80, 0x5c, 0x0, 0x3f, + 0x2, 0xcd, 0xcc, 0x50, + + /* U+0068 "h" */ + 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x1f, 0x7d, + 0xd2, 0x1f, 0x80, 0x89, 0x1f, 0x0, 0x5a, 0x1f, + 0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a, + + /* U+0069 "i" */ + 0x5, 0xe0, 0x0, 0x28, 0x0, 0xad, 0xf0, 0x0, + 0x1f, 0x0, 0x1, 0xf0, 0x0, 0x1f, 0x0, 0x1, + 0xf0, 0xd, 0xdf, 0xd9, + + /* U+006A "j" */ + 0x0, 0x5, 0xe0, 0x0, 0x2, 0x80, 0xd, 0xdd, + 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, + 0x1, 0xe0, 0x0, 0x1, 0xe0, 0x0, 0x1, 0xe0, + 0x0, 0x6, 0xb0, 0x2d, 0xdc, 0x20, + + /* U+006B "k" */ + 0xf1, 0x0, 0x0, 0xf1, 0x0, 0x0, 0xf1, 0xb, + 0x90, 0xf1, 0xa9, 0x0, 0xfb, 0xa0, 0x0, 0xf6, + 0xd1, 0x0, 0xf1, 0x7d, 0x0, 0xf1, 0x9, 0xc0, + + /* U+006C "l" */ + 0xad, 0xf0, 0x0, 0x1f, 0x0, 0x1, 0xf0, 0x0, + 0x1f, 0x0, 0x1, 0xf0, 0x0, 0x1f, 0x0, 0x1, + 0xf0, 0xd, 0xdf, 0xd9, + + /* U+006D "m" */ + 0x79, 0xd7, 0xbb, 0x7, 0xc3, 0xf1, 0xe0, 0x77, + 0x2c, 0xd, 0x17, 0x72, 0xc0, 0xd1, 0x77, 0x2c, + 0xd, 0x17, 0x72, 0xc0, 0xd1, + + /* U+006E "n" */ + 0x1e, 0x8c, 0xd2, 0x1f, 0x60, 0x79, 0x1f, 0x0, + 0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f, + 0x0, 0x5a, + + /* U+006F "o" */ + 0x4, 0xdd, 0xb2, 0x1, 0xe2, 0x7, 0xb0, 0x5a, + 0x0, 0xf, 0x6, 0xa0, 0x0, 0xf0, 0x2e, 0x20, + 0x7a, 0x0, 0x6d, 0xda, 0x10, + + /* U+0070 "p" */ + 0x1e, 0x8c, 0xd2, 0x1f, 0x70, 0x5b, 0x1f, 0x0, + 0x1e, 0x1f, 0x0, 0x2d, 0x1f, 0x0, 0x99, 0x1f, + 0xed, 0xa0, 0x1f, 0x0, 0x0, 0x1f, 0x0, 0x0, + + /* U+0071 "q" */ + 0x0, 0x0, 0x0, 0x3, 0xcd, 0xd9, 0xe, 0x20, + 0x6a, 0x4b, 0x0, 0x6a, 0x5b, 0x0, 0x6a, 0x2e, + 0x12, 0xea, 0x8, 0xec, 0x8a, 0x0, 0x0, 0x6a, + 0x0, 0x0, 0x6a, + + /* U+0072 "r" */ + 0xd6, 0xcd, 0x60, 0xdb, 0x2, 0xe0, 0xd3, 0x0, + 0x40, 0xd3, 0x0, 0x0, 0xd3, 0x0, 0x0, 0xd3, + 0x0, 0x0, + + /* U+0073 "s" */ + 0x4c, 0xdd, 0x2c, 0x40, 0x0, 0x7d, 0x71, 0x0, + 0x28, 0xe4, 0x10, 0x9, 0x8c, 0xee, 0xb1, + + /* U+0074 "t" */ + 0x0, 0xb0, 0x0, 0x0, 0xf0, 0x0, 0x8d, 0xfd, + 0xd9, 0x0, 0xf0, 0x0, 0x0, 0xf0, 0x0, 0x0, + 0xf0, 0x0, 0x0, 0xe3, 0x0, 0x0, 0x5d, 0xd9, + + /* U+0075 "u" */ + 0x1f, 0x0, 0x5a, 0x1f, 0x0, 0x5a, 0x1f, 0x0, + 0x5a, 0xf, 0x0, 0x5a, 0xf, 0x10, 0xca, 0x7, + 0xdc, 0x8a, + + /* U+0076 "v" */ + 0x6b, 0x0, 0x2f, 0x1, 0xf1, 0x7, 0x90, 0xa, + 0x70, 0xd3, 0x0, 0x4d, 0x3d, 0x0, 0x0, 0xeb, + 0x60, 0x0, 0x8, 0xf1, 0x0, + + /* U+0077 "w" */ + 0xb4, 0x0, 0xa, 0x59, 0x61, 0x50, 0xc2, 0x68, + 0x6f, 0xe, 0x4, 0xab, 0xa5, 0xe0, 0x2d, 0xb3, + 0xcb, 0x0, 0xf6, 0xd, 0x90, + + /* U+0078 "x" */ + 0x2e, 0x20, 0x7c, 0x0, 0x6c, 0x2e, 0x10, 0x0, + 0xae, 0x50, 0x0, 0xb, 0xf4, 0x0, 0x7, 0xc3, + 0xe2, 0x3, 0xe2, 0x7, 0xc0, + + /* U+0079 "y" */ + 0x6b, 0x0, 0x2e, 0x0, 0xf2, 0x8, 0x90, 0x9, + 0x80, 0xd2, 0x0, 0x2e, 0x4c, 0x0, 0x0, 0xbd, + 0x60, 0x0, 0x6, 0xe0, 0x0, 0x0, 0xc6, 0x0, + 0x9, 0xe7, 0x0, 0x0, + + /* U+007A "z" */ + 0xc, 0xdd, 0xf7, 0x0, 0x3, 0xe1, 0x0, 0x1d, + 0x30, 0x0, 0xb7, 0x0, 0x7, 0xb0, 0x0, 0xf, + 0xed, 0xd9, + + /* U+007B "{" */ + 0x0, 0xb, 0xd3, 0x0, 0x5a, 0x0, 0x0, 0x68, + 0x0, 0x0, 0x87, 0x0, 0xe, 0xd1, 0x0, 0x0, + 0x97, 0x0, 0x0, 0x68, 0x0, 0x0, 0x69, 0x0, + 0x0, 0x5b, 0x0, 0x0, 0xa, 0xd3, + + /* U+007C "|" */ + 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, + 0x3c, 0x3c, 0x3c, 0x3c, + + /* U+007D "}" */ + 0x8d, 0x60, 0x0, 0x1f, 0x0, 0x0, 0xf0, 0x0, + 0xe, 0x20, 0x0, 0x5f, 0x80, 0xd, 0x20, 0x0, + 0xf0, 0x0, 0xf, 0x0, 0x1, 0xe0, 0x8, 0xd5, + 0x0, + + /* U+007E "~" */ + 0x3d, 0xd7, 0x8, 0x15, 0x42, 0xae, 0xa0, + + /* U+007F "" */ + + /* U+4E2D "中" */ + 0x0, 0x0, 0xb, 0x40, 0x0, 0x0, 0x0, 0x0, + 0xb4, 0x0, 0x0, 0xa, 0xaa, 0xae, 0xca, 0xaa, + 0x50, 0xf3, 0x33, 0xc6, 0x33, 0x88, 0xf, 0x0, + 0xb, 0x40, 0x6, 0x80, 0xf0, 0x0, 0xb4, 0x0, + 0x68, 0xf, 0xdd, 0xdf, 0xed, 0xde, 0x80, 0xa0, + 0x0, 0xb5, 0x0, 0x45, 0x0, 0x0, 0xb, 0x40, + 0x0, 0x0, 0x0, 0x0, 0xb4, 0x0, 0x0, 0x0, + 0x0, 0xb, 0x40, 0x0, 0x0, 0x0, 0x0, 0xb4, + 0x0, 0x0, + + /* U+6587 "æ–‡" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc, 0x10, 0x0, 0x0, 0x0, 0x0, 0x8, 0x70, + 0x0, 0x0, 0xce, 0xee, 0xee, 0xee, 0xee, 0xe5, + 0x0, 0x86, 0x0, 0x0, 0xe1, 0x0, 0x0, 0x3b, + 0x0, 0x3, 0xc0, 0x0, 0x0, 0xc, 0x20, 0x9, + 0x60, 0x0, 0x0, 0x4, 0xc0, 0x3d, 0x0, 0x0, + 0x0, 0x0, 0x9a, 0xe3, 0x0, 0x0, 0x0, 0x0, + 0x6f, 0xd2, 0x0, 0x0, 0x0, 0x5c, 0xc3, 0x7e, + 0xa4, 0x0, 0x8e, 0xc4, 0x0, 0x1, 0x8e, 0xf2, + 0x22, 0x0, 0x0, 0x0, 0x0, 0x30 +}; + + +static const sgl_font_table_t sgl_ascii_consolas14_tab[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 106, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 106, .box_w = 3, .box_h = 8, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 12, .adv_w = 106, .box_w = 5, .box_h = 3, .ofs_x = 1, .ofs_y = 5}, + {.bitmap_index = 20, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 48, .adv_w = 106, .box_w = 6, .box_h = 12, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 84, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 112, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 140, .adv_w = 106, .box_w = 2, .box_h = 3, .ofs_x = 2, .ofs_y = 5}, + {.bitmap_index = 143, .adv_w = 106, .box_w = 5, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 173, .adv_w = 106, .box_w = 4, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 197, .adv_w = 106, .box_w = 6, .box_h = 5, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 212, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 233, .adv_w = 106, .box_w = 4, .box_h = 5, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 243, .adv_w = 106, .box_w = 5, .box_h = 1, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 246, .adv_w = 106, .box_w = 3, .box_h = 2, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 249, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 277, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 305, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 329, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 353, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 377, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 405, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 425, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 449, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 473, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 497, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 521, .adv_w = 106, .box_w = 3, .box_h = 6, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 530, .adv_w = 106, .box_w = 4, .box_h = 8, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 546, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 570, .adv_w = 106, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 579, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 599, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 619, .adv_w = 106, .box_w = 7, .box_h = 10, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 654, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 682, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 706, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 730, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 758, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 778, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 798, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 822, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 846, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 866, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 886, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 914, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 934, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 962, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 986, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1014, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1038, .adv_w = 106, .box_w = 7, .box_h = 10, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1073, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1097, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1121, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1149, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1173, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1201, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1229, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1257, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1285, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1309, .adv_w = 106, .box_w = 3, .box_h = 10, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 1324, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1354, .adv_w = 106, .box_w = 4, .box_h = 10, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 1374, .adv_w = 106, .box_w = 6, .box_h = 4, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 1386, .adv_w = 106, .box_w = 7, .box_h = 1, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1390, .adv_w = 49, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 6}, + {.bitmap_index = 1395, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1413, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1437, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1455, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1479, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1497, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1525, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1553, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1577, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1597, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1627, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1651, .adv_w = 106, .box_w = 5, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1671, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1692, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1710, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1731, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1755, .adv_w = 106, .box_w = 6, .box_h = 9, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1782, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1800, .adv_w = 106, .box_w = 5, .box_h = 6, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1815, .adv_w = 106, .box_w = 6, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1839, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1857, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1878, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1899, .adv_w = 106, .box_w = 7, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1920, .adv_w = 106, .box_w = 7, .box_h = 8, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1948, .adv_w = 106, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1966, .adv_w = 106, .box_w = 6, .box_h = 10, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1996, .adv_w = 106, .box_w = 2, .box_h = 12, .ofs_x = 2, .ofs_y = -2}, + {.bitmap_index = 2008, .adv_w = 106, .box_w = 5, .box_h = 10, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 2033, .adv_w = 106, .box_w = 7, .box_h = 2, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 2040, .adv_w = 106, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2040, .adv_w = 192, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 2106, .adv_w = 192, .box_w = 12, .box_h = 13, .ofs_x = 0, .ofs_y = -2} +}; + +static const uint32_t unicode_list_1[] = { + 0x0, 0x175a +}; + +static const sgl_font_unicode_t consolas14_unicode[] = { + { .offset = 32, .len = 96, .list = NULL, .tab_offset = 1, }, + { .offset = 20013, .len = 2, .list = unicode_list_1, .tab_offset = 97, }, +}; + +const sgl_font_t consolas14 = { + .bitmap = sgl_ascii_consolas14_bitmap, + .table = sgl_ascii_consolas14_tab, + .font_table_size = SGL_ARRAY_SIZE(sgl_ascii_consolas14_tab), + .font_height = 14, + .base_line = 3, + .bpp = 4, + .unicode = consolas14_unicode, + .unicode_num = 2, +}; + + +#endif // !CONFIG_SGL_FONT_CONSOLAS14 diff --git a/User/system/sgl/fonts/sgl_ascii_consolas23.c b/User/system/sgl/fonts/sgl_ascii_consolas23.c new file mode 100644 index 0000000..dd3e780 --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_consolas23.c @@ -0,0 +1,1198 @@ +/* source/fonts/sgl_ascii_consolas23.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + + +#if (CONFIG_SGL_FONT_CONSOLAS23) + + +static const uint8_t sgl_ascii_consolas23_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0x5f, 0xd0, 0x4f, 0xc0, 0x4f, 0xc0, 0x3f, 0xb0, + 0x3f, 0xb0, 0x2f, 0xa0, 0x2f, 0xa0, 0x1f, 0xa0, + 0x1f, 0x90, 0x1f, 0x90, 0x9, 0x50, 0x0, 0x0, + 0x2c, 0x70, 0x8f, 0xf0, 0x4e, 0xa0, + + /* U+0022 "\"" */ + 0x5f, 0xe0, 0x5f, 0xd4, 0xfd, 0x4, 0xfd, 0x3f, + 0xc0, 0x3f, 0xc2, 0xfb, 0x2, 0xfb, 0x1f, 0xa0, + 0x1f, 0xa0, 0x0, 0x0, 0x0, + + /* U+0023 "#" */ + 0x0, 0x7, 0xf0, 0x5, 0xf3, 0x0, 0x0, 0x9, + 0xe0, 0x7, 0xf1, 0x0, 0x0, 0xa, 0xd0, 0x8, + 0xf0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf1, + 0x6, 0x6f, 0xc6, 0x6d, 0xd6, 0x60, 0x0, 0xf, + 0x80, 0xd, 0xa0, 0x0, 0x0, 0xf, 0x70, 0xe, + 0x90, 0x0, 0x0, 0x2f, 0x60, 0xf, 0x80, 0x0, + 0x1, 0x4f, 0x61, 0x2f, 0x71, 0x0, 0x9f, 0xff, + 0xff, 0xff, 0xff, 0x90, 0x24, 0x9f, 0x54, 0x7f, + 0x74, 0x20, 0x0, 0x8f, 0x0, 0x6f, 0x20, 0x0, + 0x0, 0x9e, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xbd, + 0x0, 0x9f, 0x0, 0x0, + + /* U+0024 "$" */ + 0x0, 0x0, 0xf, 0x70, 0x0, 0x0, 0x0, 0x1f, + 0x50, 0x0, 0x1, 0x8d, 0xff, 0xfc, 0x30, 0x1d, + 0xfb, 0xbf, 0xac, 0x50, 0x8f, 0x70, 0x8f, 0x0, + 0x0, 0xbf, 0x30, 0xad, 0x0, 0x0, 0x9f, 0x90, + 0xcb, 0x0, 0x0, 0x1e, 0xfd, 0xf9, 0x0, 0x0, + 0x2, 0xbf, 0xfe, 0x70, 0x0, 0x0, 0x4, 0xff, + 0xfd, 0x20, 0x0, 0x4, 0xf3, 0x8f, 0xd0, 0x0, + 0x7, 0xf0, 0xc, 0xf3, 0x0, 0x9, 0xe0, 0xb, + 0xf4, 0x63, 0x1b, 0xc0, 0x6f, 0xf0, 0xdf, 0xff, + 0xff, 0xff, 0x60, 0x7c, 0xff, 0xfe, 0xa3, 0x0, + 0x0, 0xf, 0x70, 0x0, 0x0, 0x0, 0x3f, 0x40, + 0x0, 0x0, 0x0, 0x13, 0x0, 0x0, 0x0, + + /* U+0025 "%" */ + 0x5, 0xde, 0x90, 0x0, 0xa, 0xe1, 0x3f, 0x85, + 0xf8, 0x0, 0x4f, 0x60, 0x8f, 0x0, 0xbc, 0x0, + 0xec, 0x0, 0x9e, 0x0, 0xac, 0x9, 0xf2, 0x0, + 0x6f, 0x53, 0xf9, 0x3f, 0x80, 0x0, 0xb, 0xff, + 0xc1, 0xcd, 0x0, 0x0, 0x0, 0x22, 0x7, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0x90, 0x0, 0x0, + 0x0, 0x0, 0xbe, 0x10, 0x0, 0x0, 0x0, 0x5, + 0xf5, 0x3d, 0xfd, 0x30, 0x0, 0x1e, 0xb0, 0xec, + 0x5d, 0xd0, 0x0, 0x9f, 0x24, 0xf3, 0x6, 0xf1, + 0x3, 0xf7, 0x4, 0xf3, 0x6, 0xf1, 0xd, 0xd0, + 0x1, 0xfb, 0x4d, 0xc0, 0x7f, 0x30, 0x0, 0x4d, + 0xfb, 0x10, + + /* U+0026 "&" */ + 0x0, 0x8, 0xef, 0xc4, 0x0, 0x0, 0x0, 0x9f, + 0xca, 0xff, 0x30, 0x0, 0x1, 0xfd, 0x0, 0x5f, + 0x80, 0x0, 0x3, 0xfa, 0x0, 0x2f, 0xa0, 0x0, + 0x2, 0xfd, 0x0, 0x7f, 0x60, 0x0, 0x0, 0xcf, + 0x57, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0x8f, 0xfd, 0x0, 0x15, 0x20, + 0x8, 0xfa, 0xcf, 0x90, 0x5f, 0x70, 0x1f, 0xd0, + 0x1e, 0xf5, 0x7f, 0x50, 0x5f, 0x70, 0x4, 0xff, + 0xcf, 0x20, 0x6f, 0x80, 0x0, 0x7f, 0xfc, 0x0, + 0x3f, 0xd0, 0x0, 0xe, 0xfa, 0x0, 0xa, 0xfd, + 0x88, 0xdf, 0xff, 0x60, 0x0, 0x7d, 0xfe, 0xb3, + 0x3f, 0xf3, + + /* U+0027 "'" */ + 0x5f, 0xe4, 0xfd, 0x4f, 0xc3, 0xfb, 0x2f, 0xa0, + 0x0, + + /* U+0028 "(" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x8, + 0xf8, 0x0, 0x5f, 0xb0, 0x1, 0xee, 0x10, 0x8, + 0xf6, 0x0, 0xf, 0xe0, 0x0, 0x5f, 0x80, 0x0, + 0x9f, 0x30, 0x0, 0xbf, 0x10, 0x0, 0xdf, 0x0, + 0x0, 0xef, 0x0, 0x0, 0xdf, 0x0, 0x0, 0xbf, + 0x20, 0x0, 0x8f, 0x60, 0x0, 0x3f, 0xb0, 0x0, + 0xc, 0xf2, 0x0, 0x4, 0xfb, 0x0, 0x0, 0xbf, + 0x50, 0x0, 0x1e, 0xf3, 0x0, 0x3, 0xfa, 0x0, + 0x0, 0x30, + + /* U+0029 ")" */ + 0x0, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x1e, + 0xf2, 0x0, 0x0, 0x3f, 0xd0, 0x0, 0x0, 0x7f, + 0x80, 0x0, 0x0, 0xdf, 0x20, 0x0, 0x5, 0xf8, + 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xbf, 0x20, + 0x0, 0x8, 0xf5, 0x0, 0x0, 0x7f, 0x60, 0x0, + 0x6, 0xf6, 0x0, 0x0, 0x7f, 0x50, 0x0, 0x9, + 0xf3, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x2f, 0xb0, + 0x0, 0x8, 0xf4, 0x0, 0x2, 0xfc, 0x0, 0x0, + 0xbf, 0x30, 0x0, 0x8f, 0x70, 0x0, 0x1f, 0xa0, + 0x0, 0x0, 0x30, 0x0, 0x0, + + /* U+002A "*" */ + 0x0, 0x0, 0xe7, 0x0, 0x0, 0x20, 0xd, 0x60, + 0x1, 0x1f, 0x90, 0xc5, 0x3d, 0xa0, 0x5d, 0xdd, + 0xbf, 0xa2, 0x0, 0xa, 0xff, 0x40, 0x0, 0x3b, + 0xee, 0xcf, 0x81, 0x1f, 0xa1, 0xc5, 0x4e, 0xa0, + 0x30, 0xd, 0x60, 0x11, 0x0, 0x0, 0xe7, 0x0, + 0x0, 0x0, 0x1, 0x10, 0x0, + + /* U+002B "+" */ + 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x0, 0x1, + 0xfa, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xa0, 0x0, + 0x0, 0x0, 0x1, 0xfa, 0x0, 0x0, 0x1a, 0xaa, + 0xaf, 0xea, 0xaa, 0x72, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x0, + 0x1, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xa0, + 0x0, 0x0, 0x0, 0x1, 0xfa, 0x0, 0x0, 0x0, + 0x0, 0x6, 0x30, 0x0, 0x0, + + /* U+002C "," */ + 0x0, 0x3a, 0x40, 0x0, 0xcf, 0xf1, 0x0, 0x8f, + 0xf5, 0x0, 0xf, 0xf5, 0x0, 0xf, 0xf1, 0x14, + 0xcf, 0x80, 0x9f, 0xe7, 0x0, 0x23, 0x0, 0x0, + + /* U+002D "-" */ + 0x3c, 0xcc, 0xcc, 0xa4, 0xff, 0xff, 0xfd, + + /* U+002E "." */ + 0x1, 0x84, 0x0, 0xdf, 0xf3, 0xf, 0xff, 0x50, + 0x6f, 0xb0, + + /* U+002F "/" */ + 0x0, 0x0, 0x0, 0x0, 0xa, 0xe1, 0x0, 0x0, + 0x0, 0x0, 0x4f, 0x60, 0x0, 0x0, 0x0, 0x0, + 0xec, 0x0, 0x0, 0x0, 0x0, 0x9, 0xf2, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, + 0x0, 0xcd, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0x90, 0x0, 0x0, + 0x0, 0x0, 0xbe, 0x10, 0x0, 0x0, 0x0, 0x5, + 0xf5, 0x0, 0x0, 0x0, 0x0, 0x1e, 0xb0, 0x0, + 0x0, 0x0, 0x0, 0x9f, 0x20, 0x0, 0x0, 0x0, + 0x3, 0xf7, 0x0, 0x0, 0x0, 0x0, 0xd, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x30, 0x0, 0x0, + 0x0, 0x0, + + /* U+0030 "0" */ + 0x0, 0x5, 0xcf, 0xeb, 0x20, 0x0, 0x7, 0xfe, + 0xac, 0xff, 0x30, 0x2, 0xfd, 0x10, 0x6, 0xfc, + 0x0, 0x9f, 0x40, 0x0, 0xc, 0xf2, 0xd, 0xf0, + 0x0, 0x5, 0xff, 0x60, 0xfc, 0x0, 0x8, 0xfe, + 0xf8, 0x1f, 0xb0, 0x1c, 0xfa, 0x3f, 0x91, 0xfb, + 0x3e, 0xf6, 0x2, 0xf9, 0xf, 0xef, 0xd2, 0x0, + 0x3f, 0x80, 0xef, 0xa0, 0x0, 0x6, 0xf6, 0xa, + 0xf4, 0x0, 0x0, 0xbf, 0x20, 0x4f, 0xd1, 0x0, + 0x5f, 0xb0, 0x0, 0x9f, 0xea, 0xbf, 0xe2, 0x0, + 0x0, 0x7d, 0xfe, 0x91, 0x0, + + /* U+0031 "1" */ + 0x0, 0x5, 0xef, 0x30, 0x0, 0x4, 0xdf, 0xff, + 0x30, 0x0, 0x6f, 0xf8, 0xcf, 0x30, 0x0, 0x2a, + 0x10, 0xcf, 0x30, 0x0, 0x0, 0x0, 0xcf, 0x30, + 0x0, 0x0, 0x0, 0xcf, 0x30, 0x0, 0x0, 0x0, + 0xcf, 0x30, 0x0, 0x0, 0x0, 0xcf, 0x30, 0x0, + 0x0, 0x0, 0xcf, 0x30, 0x0, 0x0, 0x0, 0xcf, + 0x30, 0x0, 0x0, 0x0, 0xcf, 0x30, 0x0, 0x0, + 0x0, 0xcf, 0x30, 0x0, 0x2c, 0xcc, 0xff, 0xcc, + 0xc2, 0x3f, 0xff, 0xff, 0xff, 0xf3, + + /* U+0032 "2" */ + 0x1, 0x8d, 0xfe, 0x80, 0x0, 0x2e, 0xfc, 0xbe, + 0xfc, 0x0, 0xc, 0x40, 0x0, 0xdf, 0x50, 0x0, + 0x0, 0x0, 0x6f, 0x90, 0x0, 0x0, 0x0, 0x5f, + 0x80, 0x0, 0x0, 0x0, 0x8f, 0x50, 0x0, 0x0, + 0x2, 0xfe, 0x0, 0x0, 0x0, 0xc, 0xf4, 0x0, + 0x0, 0x0, 0xbf, 0x70, 0x0, 0x0, 0xb, 0xf8, + 0x0, 0x0, 0x0, 0xbf, 0x80, 0x0, 0x0, 0xa, + 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0xcc, 0xcc, + 0xc4, 0x8f, 0xff, 0xff, 0xff, 0xf5, + + /* U+0033 "3" */ + 0x9, 0xdf, 0xfd, 0x81, 0x0, 0xf, 0xca, 0xae, + 0xfd, 0x0, 0x0, 0x0, 0x0, 0xcf, 0x40, 0x0, + 0x0, 0x0, 0x7f, 0x60, 0x0, 0x0, 0x0, 0xaf, + 0x30, 0x0, 0x0, 0x17, 0xfa, 0x0, 0x0, 0xaf, + 0xff, 0xb0, 0x0, 0x0, 0x58, 0x9c, 0xfd, 0x20, + 0x0, 0x0, 0x0, 0x5f, 0xc0, 0x0, 0x0, 0x0, + 0xd, 0xf0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, + 0x0, 0x0, 0x8f, 0x90, 0x4c, 0xaa, 0xbe, 0xfc, + 0x10, 0x4e, 0xff, 0xeb, 0x60, 0x0, + + /* U+0034 "4" */ + 0x0, 0x0, 0x2, 0xff, 0xb0, 0x0, 0x0, 0x0, + 0xcf, 0xfb, 0x0, 0x0, 0x0, 0x5f, 0x9f, 0xb0, + 0x0, 0x0, 0x1e, 0xd2, 0xfb, 0x0, 0x0, 0x9, + 0xf3, 0x1f, 0xb0, 0x0, 0x3, 0xf9, 0x1, 0xfb, + 0x0, 0x0, 0xce, 0x10, 0x1f, 0xb0, 0x0, 0x6f, + 0x50, 0x1, 0xfb, 0x0, 0x1f, 0xb0, 0x0, 0x1f, + 0xb0, 0x8, 0xfc, 0xaa, 0xaa, 0xfe, 0xaa, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x1, + 0xfb, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xb0, 0x0, + 0x0, 0x0, 0x1, 0xfb, 0x0, + + /* U+0035 "5" */ + 0xf, 0xff, 0xff, 0xff, 0x40, 0xfe, 0xaa, 0xaa, + 0xa2, 0xf, 0xc0, 0x0, 0x0, 0x0, 0xfc, 0x0, + 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0xfe, + 0x98, 0x73, 0x0, 0xf, 0xff, 0xff, 0xfa, 0x0, + 0x0, 0x1, 0x5d, 0xf8, 0x0, 0x0, 0x0, 0x2f, + 0xe0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, + 0x2f, 0xd0, 0x0, 0x0, 0x1c, 0xf6, 0x2c, 0xaa, + 0xcf, 0xf8, 0x2, 0xef, 0xfe, 0xa3, 0x0, + + /* U+0036 "6" */ + 0x0, 0x3, 0x9d, 0xff, 0x70, 0x0, 0x7f, 0xfc, + 0xaa, 0x40, 0x6, 0xfa, 0x10, 0x0, 0x0, 0xe, + 0xc0, 0x0, 0x0, 0x0, 0x4f, 0x60, 0x0, 0x0, + 0x0, 0x8f, 0x6a, 0xdf, 0xd8, 0x0, 0xaf, 0xfd, + 0x99, 0xef, 0xa0, 0xbf, 0x50, 0x0, 0xd, 0xf3, + 0xbf, 0x20, 0x0, 0x7, 0xf6, 0xaf, 0x30, 0x0, + 0x6, 0xf7, 0x7f, 0x70, 0x0, 0x8, 0xf5, 0x2f, + 0xd1, 0x0, 0x2f, 0xe0, 0x8, 0xfe, 0x9a, 0xff, + 0x50, 0x0, 0x6d, 0xfe, 0xb3, 0x0, + + /* U+0037 "7" */ + 0xcf, 0xff, 0xff, 0xff, 0xf4, 0x9c, 0xcc, 0xcc, + 0xce, 0xf4, 0x0, 0x0, 0x0, 0xe, 0xe0, 0x0, + 0x0, 0x0, 0x6f, 0x70, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0x5, 0xf8, 0x0, 0x0, 0x0, + 0xd, 0xf1, 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, + 0x0, 0x0, 0xcf, 0x20, 0x0, 0x0, 0x4, 0xfb, + 0x0, 0x0, 0x0, 0xb, 0xf3, 0x0, 0x0, 0x0, + 0x3f, 0xc0, 0x0, 0x0, 0x0, 0xaf, 0x50, 0x0, + 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, + + /* U+0038 "8" */ + 0x0, 0x7d, 0xff, 0xc5, 0x0, 0xb, 0xfc, 0x9a, + 0xef, 0x80, 0x5f, 0x90, 0x0, 0x1f, 0xe0, 0x7f, + 0x60, 0x0, 0xd, 0xf0, 0x4f, 0xc0, 0x0, 0x3f, + 0xb0, 0xa, 0xfd, 0x56, 0xfe, 0x20, 0x0, 0x8f, + 0xff, 0xd1, 0x0, 0x2, 0xdf, 0xcf, 0xfb, 0x0, + 0x1e, 0xf4, 0x1, 0xcf, 0xb0, 0x9f, 0x60, 0x0, + 0xe, 0xf2, 0xbf, 0x30, 0x0, 0xa, 0xf4, 0xaf, + 0x80, 0x0, 0x1e, 0xf2, 0x3f, 0xfd, 0xaa, 0xff, + 0x90, 0x2, 0xad, 0xfe, 0xb5, 0x0, + + /* U+0039 "9" */ + 0x0, 0x7d, 0xfe, 0x91, 0x0, 0xc, 0xfc, 0x9b, + 0xfe, 0x10, 0x8f, 0x80, 0x0, 0x6f, 0x80, 0xdf, + 0x10, 0x0, 0xe, 0xe0, 0xff, 0x0, 0x0, 0xb, + 0xf1, 0xdf, 0x10, 0x0, 0x9, 0xf3, 0x7f, 0xc2, + 0x2, 0x7e, 0xf3, 0xa, 0xff, 0xff, 0xfe, 0xf3, + 0x0, 0x47, 0x75, 0x1b, 0xf1, 0x0, 0x0, 0x0, + 0xe, 0xd0, 0x0, 0x0, 0x0, 0x6f, 0x70, 0x0, + 0x0, 0x6, 0xfd, 0x0, 0x1a, 0xac, 0xff, 0xd2, + 0x0, 0x2f, 0xfe, 0xb6, 0x0, 0x0, + + /* U+003A ":" */ + 0x4e, 0xb0, 0xbf, 0xf4, 0x8f, 0xf1, 0x3, 0x10, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x10, + 0x7f, 0xe1, 0xbf, 0xf4, 0x4e, 0xb0, + + /* U+003B ";" */ + 0x0, 0x4e, 0xb0, 0x0, 0xbf, 0xf4, 0x0, 0x8f, + 0xf1, 0x0, 0x3, 0x10, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x50, + 0x0, 0x9f, 0xf3, 0x0, 0x7f, 0xf7, 0x0, 0xe, + 0xf7, 0x0, 0xd, 0xf3, 0x14, 0xaf, 0xa0, 0x7f, + 0xf8, 0x0, 0x23, 0x0, 0x0, + + /* U+003C "<" */ + 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x5f, + 0xe2, 0x0, 0x0, 0x7f, 0xd2, 0x0, 0x0, 0x9f, + 0xc1, 0x0, 0x0, 0xaf, 0xa0, 0x0, 0x1, 0xcf, + 0x80, 0x0, 0x0, 0x3e, 0xf4, 0x0, 0x0, 0x0, + 0x2e, 0xf6, 0x0, 0x0, 0x0, 0x1c, 0xf8, 0x0, + 0x0, 0x0, 0xb, 0xfa, 0x0, 0x0, 0x0, 0x9, + 0xfc, 0x10, 0x0, 0x0, 0x7, 0xd1, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+003D "=" */ + 0x59, 0x99, 0x99, 0x99, 0x91, 0xaf, 0xff, 0xff, + 0xff, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x59, 0x99, 0x99, 0x99, + 0x91, 0xaf, 0xff, 0xff, 0xff, 0xf3, + + /* U+003E ">" */ + 0x29, 0x0, 0x0, 0x0, 0x8, 0xfc, 0x10, 0x0, + 0x0, 0x7, 0xfd, 0x20, 0x0, 0x0, 0x5, 0xfe, + 0x30, 0x0, 0x0, 0x3, 0xef, 0x40, 0x0, 0x0, + 0x2, 0xdf, 0x60, 0x0, 0x0, 0xa, 0xfb, 0x0, + 0x0, 0x1c, 0xf9, 0x0, 0x0, 0x2d, 0xf7, 0x0, + 0x0, 0x3e, 0xf5, 0x0, 0x0, 0x5f, 0xe3, 0x0, + 0x0, 0x6, 0xd2, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+003F "?" */ + 0xde, 0xb5, 0x0, 0xa, 0xdf, 0xfb, 0x0, 0x0, + 0x2b, 0xfb, 0x0, 0x0, 0xd, 0xf3, 0x0, 0x0, + 0x8f, 0x60, 0x0, 0x9, 0xf5, 0x1, 0x25, 0xff, + 0x10, 0xdf, 0xfe, 0x50, 0xd, 0xe3, 0x0, 0x0, + 0xcd, 0x0, 0x0, 0x9, 0x90, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xa, 0xa0, 0x0, 0x4, 0xff, 0x40, + 0x0, 0x1d, 0xd1, 0x0, 0x0, + + /* U+0040 "@" */ + 0x0, 0x0, 0x6d, 0xfe, 0x91, 0x0, 0x0, 0xb, + 0xf9, 0x57, 0xed, 0x0, 0x0, 0x9f, 0x30, 0x0, + 0x2f, 0x70, 0x3, 0xf6, 0x0, 0x0, 0x9, 0xe0, + 0xa, 0xe0, 0x0, 0x0, 0x5, 0xf2, 0x1f, 0x80, + 0x4e, 0xfe, 0xb2, 0xf4, 0x5f, 0x21, 0xfb, 0x6f, + 0x91, 0xf5, 0x8f, 0x8, 0xf1, 0x2f, 0x60, 0xf6, + 0xbc, 0xd, 0xc0, 0x5f, 0x41, 0xf5, 0xca, 0xf, + 0x90, 0x7f, 0x22, 0xf4, 0xd9, 0x1f, 0x80, 0x9f, + 0x3, 0xf2, 0xe9, 0x1f, 0x80, 0xce, 0x7, 0xf0, + 0xd9, 0xf, 0xb6, 0xff, 0x3d, 0x90, 0xbb, 0x9, + 0xff, 0x5f, 0xfd, 0x10, 0x9e, 0x0, 0x32, 0x1, + 0x40, 0x0, 0x4f, 0x40, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xfd, + 0x75, 0x7a, 0xa0, 0x0, 0x0, 0x3b, 0xef, 0xd9, + 0x30, 0x0, + + /* U+0041 "A" */ + 0x0, 0x0, 0x9f, 0xf3, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xf8, 0x0, 0x0, 0x0, 0x3, 0xf9, 0xfd, + 0x0, 0x0, 0x0, 0x9, 0xf3, 0xbf, 0x20, 0x0, + 0x0, 0xe, 0xe0, 0x7f, 0x70, 0x0, 0x0, 0x3f, + 0x90, 0x2f, 0xc0, 0x0, 0x0, 0x8f, 0x40, 0xd, + 0xf1, 0x0, 0x0, 0xdf, 0x0, 0x8, 0xf6, 0x0, + 0x2, 0xfb, 0x0, 0x3, 0xfb, 0x0, 0x7, 0xfd, + 0xbb, 0xbb, 0xff, 0x0, 0xc, 0xff, 0xff, 0xff, + 0xff, 0x50, 0x1f, 0xc0, 0x0, 0x0, 0x5f, 0xa0, + 0x6f, 0x70, 0x0, 0x0, 0xf, 0xf0, 0xbf, 0x20, + 0x0, 0x0, 0xb, 0xf4, + + /* U+0042 "B" */ + 0x6f, 0xff, 0xfe, 0xb5, 0x0, 0x6f, 0xc9, 0x9c, + 0xff, 0x60, 0x6f, 0x70, 0x0, 0x5f, 0xd0, 0x6f, + 0x70, 0x0, 0xf, 0xe0, 0x6f, 0x70, 0x0, 0x2f, + 0xc0, 0x6f, 0x70, 0x3, 0xcf, 0x40, 0x6f, 0xff, + 0xff, 0xf5, 0x0, 0x6f, 0xc9, 0x9c, 0xff, 0x60, + 0x6f, 0x70, 0x0, 0x3f, 0xf2, 0x6f, 0x70, 0x0, + 0x9, 0xf5, 0x6f, 0x70, 0x0, 0x9, 0xf5, 0x6f, + 0x70, 0x0, 0x2f, 0xf1, 0x6f, 0xc9, 0xab, 0xff, + 0x60, 0x6f, 0xff, 0xfe, 0xa3, 0x0, + + /* U+0043 "C" */ + 0x0, 0x0, 0x7d, 0xff, 0xd8, 0x10, 0x1, 0xdf, + 0xfc, 0xce, 0xf3, 0x0, 0xcf, 0x90, 0x0, 0x4, + 0x10, 0x5f, 0xb0, 0x0, 0x0, 0x0, 0xb, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0x30, 0x0, 0x0, 0x0, 0x8, + 0xfa, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, + 0x0, 0x31, 0x0, 0x4f, 0xfe, 0xbc, 0xef, 0x30, + 0x0, 0x29, 0xdf, 0xec, 0x81, + + /* U+0044 "D" */ + 0xef, 0xff, 0xec, 0x70, 0x0, 0xef, 0x99, 0xbe, + 0xfd, 0x20, 0xef, 0x0, 0x0, 0x9f, 0xc0, 0xef, + 0x0, 0x0, 0xc, 0xf4, 0xef, 0x0, 0x0, 0x6, + 0xf8, 0xef, 0x0, 0x0, 0x3, 0xfb, 0xef, 0x0, + 0x0, 0x2, 0xfc, 0xef, 0x0, 0x0, 0x2, 0xfb, + 0xef, 0x0, 0x0, 0x4, 0xfa, 0xef, 0x0, 0x0, + 0x7, 0xf7, 0xef, 0x0, 0x0, 0xe, 0xf2, 0xef, + 0x0, 0x1, 0xcf, 0x90, 0xef, 0xaa, 0xcf, 0xf9, + 0x0, 0xef, 0xff, 0xea, 0x40, 0x0, + + /* U+0045 "E" */ + 0xff, 0xff, 0xff, 0xfb, 0xff, 0x99, 0x99, 0x96, + 0xfe, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0xfe, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, 0xf7, 0xff, 0xaa, 0xaa, 0xa4, + 0xfe, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0xfe, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0xff, 0xaa, 0xaa, 0xa7, 0xff, 0xff, 0xff, 0xfb, + + /* U+0046 "F" */ + 0xef, 0xff, 0xff, 0xfa, 0xef, 0xaa, 0xaa, 0xa6, + 0xef, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0xef, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0xef, 0xff, 0xff, 0xf5, 0xef, 0x99, 0x99, 0x93, + 0xef, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0xef, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0xef, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + + /* U+0047 "G" */ + 0x0, 0x1, 0x8d, 0xff, 0xd9, 0x10, 0x3, 0xef, + 0xfc, 0xce, 0xf5, 0x1, 0xef, 0x80, 0x0, 0x3, + 0x20, 0x9f, 0x80, 0x0, 0x0, 0x0, 0xf, 0xf1, + 0x0, 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, 0x0, + 0x0, 0x4f, 0x90, 0x2, 0xff, 0xff, 0x64, 0xfa, + 0x0, 0x19, 0x9c, 0xf6, 0x3f, 0xb0, 0x0, 0x0, + 0x6f, 0x61, 0xfe, 0x0, 0x0, 0x6, 0xf6, 0xc, + 0xf5, 0x0, 0x0, 0x6f, 0x60, 0x4f, 0xf5, 0x0, + 0x6, 0xf6, 0x0, 0x7f, 0xfe, 0xbb, 0xef, 0x60, + 0x0, 0x3a, 0xef, 0xfc, 0x81, + + /* U+0048 "H" */ + 0xdf, 0x0, 0x0, 0x6, 0xf6, 0xdf, 0x0, 0x0, + 0x6, 0xf6, 0xdf, 0x0, 0x0, 0x6, 0xf6, 0xdf, + 0x0, 0x0, 0x6, 0xf6, 0xdf, 0x0, 0x0, 0x6, + 0xf6, 0xdf, 0x0, 0x0, 0x6, 0xf6, 0xdf, 0xff, + 0xff, 0xff, 0xf6, 0xdf, 0xaa, 0xaa, 0xac, 0xf6, + 0xdf, 0x0, 0x0, 0x6, 0xf6, 0xdf, 0x0, 0x0, + 0x6, 0xf6, 0xdf, 0x0, 0x0, 0x6, 0xf6, 0xdf, + 0x0, 0x0, 0x6, 0xf6, 0xdf, 0x0, 0x0, 0x6, + 0xf6, 0xdf, 0x0, 0x0, 0x6, 0xf6, + + /* U+0049 "I" */ + 0x3f, 0xff, 0xff, 0xff, 0xc2, 0x99, 0xaf, 0xe9, + 0x97, 0x0, 0x2, 0xfb, 0x0, 0x0, 0x0, 0x2f, + 0xb0, 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, 0x0, + 0x2f, 0xb0, 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, + 0x0, 0x2f, 0xb0, 0x0, 0x0, 0x2, 0xfb, 0x0, + 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x0, 0x2, 0xfb, + 0x0, 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x2a, 0xab, + 0xfe, 0xaa, 0x83, 0xff, 0xff, 0xff, 0xfc, + + /* U+004A "J" */ + 0xf, 0xff, 0xff, 0xff, 0xa, 0xaa, 0xaa, 0xff, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xfe, 0x15, 0x0, 0x7, 0xfa, + 0x2f, 0xeb, 0xcf, 0xe2, 0x8, 0xdf, 0xea, 0x20, + + /* U+004B "K" */ + 0x6f, 0x60, 0x0, 0x1e, 0xf2, 0x6f, 0x60, 0x0, + 0xcf, 0x40, 0x6f, 0x60, 0x8, 0xf8, 0x0, 0x6f, + 0x60, 0x4f, 0xb0, 0x0, 0x6f, 0x62, 0xed, 0x10, + 0x0, 0x6f, 0x7c, 0xf2, 0x0, 0x0, 0x6f, 0xef, + 0x60, 0x0, 0x0, 0x6f, 0xbf, 0xc0, 0x0, 0x0, + 0x6f, 0x69, 0xf9, 0x0, 0x0, 0x6f, 0x60, 0xdf, + 0x50, 0x0, 0x6f, 0x60, 0x2f, 0xf2, 0x0, 0x6f, + 0x60, 0x6, 0xfd, 0x0, 0x6f, 0x60, 0x0, 0xaf, + 0x90, 0x6f, 0x60, 0x0, 0xd, 0xf5, + + /* U+004C "L" */ + 0x9f, 0x40, 0x0, 0x0, 0x9, 0xf4, 0x0, 0x0, + 0x0, 0x9f, 0x40, 0x0, 0x0, 0x9, 0xf4, 0x0, + 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, 0x9, 0xf4, + 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, 0x9, + 0xf4, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, + 0x9, 0xf4, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, + 0x0, 0x9, 0xf4, 0x0, 0x0, 0x0, 0x9f, 0xba, + 0xaa, 0xaa, 0x9, 0xff, 0xff, 0xff, 0xf1, + + /* U+004D "M" */ + 0xd, 0xf7, 0x0, 0x0, 0xff, 0x60, 0xe, 0xfd, + 0x0, 0x5, 0xff, 0x70, 0xf, 0xdf, 0x20, 0xb, + 0xcf, 0x80, 0xf, 0x8f, 0x80, 0x1f, 0x6f, 0x80, + 0xf, 0x7b, 0xd0, 0x7f, 0x1f, 0x90, 0x1f, 0x76, + 0xf3, 0xca, 0xf, 0xa0, 0x2f, 0x60, 0xfa, 0xf5, + 0xf, 0xb0, 0x3f, 0x60, 0xaf, 0xf0, 0xe, 0xb0, + 0x3f, 0x60, 0x5f, 0x90, 0xe, 0xc0, 0x4f, 0x50, + 0x6, 0x20, 0xd, 0xd0, 0x5f, 0x50, 0x0, 0x0, + 0xd, 0xe0, 0x6f, 0x40, 0x0, 0x0, 0xd, 0xe0, + 0x6f, 0x40, 0x0, 0x0, 0xc, 0xf0, 0x7f, 0x30, + 0x0, 0x0, 0xc, 0xf0, + + /* U+004E "N" */ + 0xcf, 0xc0, 0x0, 0x5, 0xf5, 0xcf, 0xf3, 0x0, + 0x5, 0xf5, 0xcf, 0xfb, 0x0, 0x5, 0xf5, 0xce, + 0xaf, 0x20, 0x5, 0xf5, 0xce, 0x4f, 0x90, 0x5, + 0xf5, 0xce, 0xd, 0xf1, 0x5, 0xf5, 0xce, 0x6, + 0xf7, 0x5, 0xf5, 0xce, 0x0, 0xee, 0x5, 0xf5, + 0xce, 0x0, 0x8f, 0x65, 0xf5, 0xce, 0x0, 0x1f, + 0xc5, 0xf5, 0xce, 0x0, 0x9, 0xf9, 0xf5, 0xce, + 0x0, 0x2, 0xff, 0xf5, 0xce, 0x0, 0x0, 0xbf, + 0xf5, 0xce, 0x0, 0x0, 0x4f, 0xf5, + + /* U+004F "O" */ + 0x0, 0x6, 0xcf, 0xeb, 0x40, 0x0, 0xa, 0xff, + 0xbc, 0xff, 0x60, 0x5, 0xfc, 0x10, 0x4, 0xff, + 0x10, 0xdf, 0x20, 0x0, 0x8, 0xf7, 0x2f, 0xd0, + 0x0, 0x0, 0x3f, 0xc5, 0xf9, 0x0, 0x0, 0x0, + 0xfe, 0x6f, 0x80, 0x0, 0x0, 0xf, 0xf6, 0xf8, + 0x0, 0x0, 0x0, 0xff, 0x5f, 0x90, 0x0, 0x0, + 0xf, 0xd3, 0xfb, 0x0, 0x0, 0x3, 0xfa, 0xe, + 0xf1, 0x0, 0x0, 0x9f, 0x60, 0x8f, 0xb0, 0x0, + 0x4f, 0xe0, 0x0, 0xcf, 0xeb, 0xcf, 0xf3, 0x0, + 0x0, 0x8d, 0xfe, 0xa2, 0x0, + + /* U+0050 "P" */ + 0x6f, 0xff, 0xfd, 0xa4, 0x0, 0x6f, 0xc9, 0xac, + 0xff, 0x60, 0x6f, 0x70, 0x0, 0x4f, 0xf1, 0x6f, + 0x70, 0x0, 0xa, 0xf5, 0x6f, 0x70, 0x0, 0x8, + 0xf6, 0x6f, 0x70, 0x0, 0xb, 0xf3, 0x6f, 0x70, + 0x0, 0x5f, 0xd0, 0x6f, 0xca, 0xbd, 0xfe, 0x30, + 0x6f, 0xff, 0xfd, 0x91, 0x0, 0x6f, 0x70, 0x0, + 0x0, 0x0, 0x6f, 0x70, 0x0, 0x0, 0x0, 0x6f, + 0x70, 0x0, 0x0, 0x0, 0x6f, 0x70, 0x0, 0x0, + 0x0, 0x6f, 0x70, 0x0, 0x0, 0x0, + + /* U+0051 "Q" */ + 0x0, 0x5, 0xcf, 0xeb, 0x40, 0x0, 0x0, 0x9f, + 0xfb, 0xcf, 0xf5, 0x0, 0x5, 0xfd, 0x10, 0x4, + 0xff, 0x10, 0xc, 0xf3, 0x0, 0x0, 0x9f, 0x70, + 0x1f, 0xc0, 0x0, 0x0, 0x3f, 0xb0, 0x4f, 0x90, + 0x0, 0x0, 0x1f, 0xe0, 0x5f, 0x80, 0x0, 0x0, + 0xf, 0xf0, 0x6f, 0x80, 0x0, 0x0, 0xf, 0xf0, + 0x5f, 0x90, 0x0, 0x0, 0xf, 0xe0, 0x4f, 0xb0, + 0x0, 0x0, 0x2f, 0xb0, 0xf, 0xf0, 0x0, 0x0, + 0x8f, 0x70, 0xa, 0xf8, 0x0, 0x1, 0xef, 0x10, + 0x2, 0xff, 0xa6, 0x7e, 0xf6, 0x0, 0x0, 0x3d, + 0xff, 0xfe, 0x60, 0x0, 0x0, 0x0, 0x4f, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xe1, 0x0, 0x20, + 0x0, 0x0, 0x6, 0xfe, 0xbc, 0xf4, 0x0, 0x0, + 0x0, 0x6c, 0xfd, 0x91, + + /* U+0052 "R" */ + 0x4f, 0xff, 0xfe, 0xa2, 0x0, 0x4f, 0xd9, 0xad, + 0xff, 0x20, 0x4f, 0x90, 0x0, 0x8f, 0x90, 0x4f, + 0x90, 0x0, 0x3f, 0xb0, 0x4f, 0x90, 0x0, 0x5f, + 0x90, 0x4f, 0x90, 0x4, 0xef, 0x30, 0x4f, 0xff, + 0xff, 0xd4, 0x0, 0x4f, 0xc8, 0xcf, 0x70, 0x0, + 0x4f, 0x90, 0xc, 0xf4, 0x0, 0x4f, 0x90, 0x3, + 0xfc, 0x0, 0x4f, 0x90, 0x0, 0xcf, 0x30, 0x4f, + 0x90, 0x0, 0x5f, 0xa0, 0x4f, 0x90, 0x0, 0xe, + 0xf1, 0x4f, 0x90, 0x0, 0x7, 0xf8, + + /* U+0053 "S" */ + 0x0, 0x7c, 0xff, 0xec, 0x30, 0xc, 0xfe, 0xba, + 0xce, 0x50, 0x7f, 0xa0, 0x0, 0x0, 0x0, 0xaf, + 0x40, 0x0, 0x0, 0x0, 0x9f, 0x80, 0x0, 0x0, + 0x0, 0x2f, 0xfa, 0x20, 0x0, 0x0, 0x3, 0xdf, + 0xfb, 0x40, 0x0, 0x0, 0x5, 0xbf, 0xfb, 0x10, + 0x0, 0x0, 0x3, 0xcf, 0xb0, 0x0, 0x0, 0x0, + 0xd, 0xf2, 0x0, 0x0, 0x0, 0xc, 0xf2, 0x20, + 0x0, 0x0, 0x4f, 0xe0, 0xde, 0xcb, 0xbd, 0xff, + 0x50, 0x8c, 0xef, 0xfd, 0x92, 0x0, + + /* U+0054 "T" */ + 0x2f, 0xff, 0xff, 0xff, 0xff, 0xa1, 0xaa, 0xab, + 0xfe, 0xaa, 0xa6, 0x0, 0x0, 0x2f, 0xb0, 0x0, + 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xb0, 0x0, 0x0, 0x0, 0x2, 0xfb, 0x0, + 0x0, 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x0, 0x0, + 0x2, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xb0, + 0x0, 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, 0x0, + 0x0, 0x2f, 0xb0, 0x0, 0x0, 0x0, 0x2, 0xfb, + 0x0, 0x0, 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x0, + 0x0, 0x2, 0xfb, 0x0, 0x0, + + /* U+0055 "U" */ + 0xef, 0x0, 0x0, 0x6, 0xf7, 0xef, 0x0, 0x0, + 0x6, 0xf7, 0xef, 0x0, 0x0, 0x6, 0xf7, 0xef, + 0x0, 0x0, 0x6, 0xf7, 0xef, 0x0, 0x0, 0x6, + 0xf7, 0xef, 0x0, 0x0, 0x6, 0xf7, 0xef, 0x0, + 0x0, 0x6, 0xf7, 0xef, 0x0, 0x0, 0x6, 0xf7, + 0xef, 0x0, 0x0, 0x6, 0xf7, 0xdf, 0x0, 0x0, + 0x7, 0xf6, 0xbf, 0x10, 0x0, 0x9, 0xf4, 0x8f, + 0x90, 0x0, 0x2f, 0xe0, 0x1e, 0xfd, 0xab, 0xff, + 0x40, 0x1, 0x9e, 0xfe, 0xb3, 0x0, + + /* U+0056 "V" */ + 0xcf, 0x40, 0x0, 0x0, 0x9, 0xf5, 0x7f, 0x90, + 0x0, 0x0, 0xe, 0xf0, 0x2f, 0xd0, 0x0, 0x0, + 0x3f, 0xa0, 0xd, 0xf2, 0x0, 0x0, 0x8f, 0x50, + 0x8, 0xf7, 0x0, 0x0, 0xdf, 0x0, 0x3, 0xfc, + 0x0, 0x2, 0xfb, 0x0, 0x0, 0xef, 0x10, 0x7, + 0xf6, 0x0, 0x0, 0x9f, 0x60, 0xb, 0xf1, 0x0, + 0x0, 0x4f, 0xb0, 0x1f, 0xb0, 0x0, 0x0, 0xe, + 0xf0, 0x5f, 0x60, 0x0, 0x0, 0xa, 0xf4, 0xaf, + 0x10, 0x0, 0x0, 0x4, 0xfa, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, + 0xaf, 0xf1, 0x0, 0x0, + + /* U+0057 "W" */ + 0x8f, 0x30, 0x0, 0x0, 0x9, 0xf0, 0x6f, 0x40, + 0x0, 0x0, 0xa, 0xf0, 0x5f, 0x50, 0x0, 0x0, + 0xa, 0xe0, 0x4f, 0x60, 0x0, 0x0, 0xb, 0xd0, + 0x3f, 0x60, 0x3, 0x10, 0xc, 0xc0, 0x2f, 0x70, + 0x1f, 0xa0, 0xd, 0xb0, 0x1f, 0x80, 0x6f, 0xf0, + 0xe, 0xa0, 0xf, 0x90, 0xbe, 0xf5, 0xf, 0x90, + 0xf, 0xa1, 0xf6, 0xfa, 0xf, 0x80, 0xe, 0xb5, + 0xf1, 0xbf, 0x1f, 0x70, 0xd, 0xca, 0xc0, 0x5f, + 0x6f, 0x60, 0xc, 0xdf, 0x70, 0xf, 0xcf, 0x50, + 0xb, 0xff, 0x20, 0xb, 0xff, 0x40, 0xa, 0xfd, + 0x0, 0x5, 0xff, 0x30, + + /* U+0058 "X" */ + 0x2f, 0xe1, 0x0, 0x0, 0x7f, 0xa0, 0x8, 0xf9, + 0x0, 0x1, 0xef, 0x10, 0x0, 0xef, 0x20, 0x9, + 0xf7, 0x0, 0x0, 0x5f, 0xb0, 0x3f, 0xd0, 0x0, + 0x0, 0xc, 0xf5, 0xcf, 0x30, 0x0, 0x0, 0x2, + 0xff, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0x0, 0xcf, 0xf4, 0x0, 0x0, + 0x0, 0x6, 0xfc, 0xfd, 0x0, 0x0, 0x0, 0x1e, + 0xf1, 0x9f, 0x80, 0x0, 0x0, 0xaf, 0x70, 0x1f, + 0xf2, 0x0, 0x4, 0xfe, 0x0, 0x7, 0xfc, 0x0, + 0xd, 0xf5, 0x0, 0x0, 0xdf, 0x50, 0x8f, 0xc0, + 0x0, 0x0, 0x4f, 0xe1, + + /* U+0059 "Y" */ + 0xbf, 0x70, 0x0, 0x0, 0xc, 0xf4, 0x3f, 0xe0, + 0x0, 0x0, 0x4f, 0xb0, 0xa, 0xf8, 0x0, 0x0, + 0xcf, 0x30, 0x2, 0xff, 0x10, 0x5, 0xfa, 0x0, + 0x0, 0x9f, 0x80, 0xd, 0xf2, 0x0, 0x0, 0x1f, + 0xf1, 0x5f, 0x90, 0x0, 0x0, 0x7, 0xf8, 0xdf, + 0x10, 0x0, 0x0, 0x0, 0xef, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xb0, 0x0, 0x0, + + /* U+005A "Z" */ + 0xaf, 0xff, 0xff, 0xff, 0xf4, 0x8c, 0xcc, 0xcc, + 0xcf, 0xf3, 0x0, 0x0, 0x0, 0x7f, 0xa0, 0x0, + 0x0, 0x2, 0xfe, 0x10, 0x0, 0x0, 0xb, 0xf5, + 0x0, 0x0, 0x0, 0x5f, 0xb0, 0x0, 0x0, 0x1, + 0xef, 0x10, 0x0, 0x0, 0xa, 0xf7, 0x0, 0x0, + 0x0, 0x4f, 0xc0, 0x0, 0x0, 0x0, 0xdf, 0x20, + 0x0, 0x0, 0x8, 0xf8, 0x0, 0x0, 0x0, 0x3f, + 0xd0, 0x0, 0x0, 0x0, 0xcf, 0xec, 0xcc, 0xcc, + 0xc4, 0xdf, 0xff, 0xff, 0xff, 0xf6, + + /* U+005B "[" */ + 0x7f, 0xff, 0xf9, 0x7f, 0x98, 0x84, 0x7f, 0x30, + 0x0, 0x7f, 0x30, 0x0, 0x7f, 0x30, 0x0, 0x7f, + 0x30, 0x0, 0x7f, 0x30, 0x0, 0x7f, 0x30, 0x0, + 0x7f, 0x30, 0x0, 0x7f, 0x30, 0x0, 0x7f, 0x30, + 0x0, 0x7f, 0x30, 0x0, 0x7f, 0x30, 0x0, 0x7f, + 0x30, 0x0, 0x7f, 0x30, 0x0, 0x7f, 0x30, 0x0, + 0x7f, 0x30, 0x0, 0x7f, 0x98, 0x84, 0x7f, 0xff, + 0xf9, + + /* U+005C "\\" */ + 0x2f, 0x80, 0x0, 0x0, 0x0, 0xc, 0xe0, 0x0, + 0x0, 0x0, 0x5, 0xf5, 0x0, 0x0, 0x0, 0x0, + 0xeb, 0x0, 0x0, 0x0, 0x0, 0x8f, 0x20, 0x0, + 0x0, 0x0, 0x2f, 0x80, 0x0, 0x0, 0x0, 0xc, + 0xe0, 0x0, 0x0, 0x0, 0x5, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0xec, 0x0, 0x0, 0x0, 0x0, 0x8f, + 0x20, 0x0, 0x0, 0x0, 0x2f, 0x80, 0x0, 0x0, + 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, 0x5, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0xec, 0x0, 0x0, 0x0, + 0x0, 0x8f, 0x20, 0x0, 0x0, 0x0, 0x2f, 0x90, + 0x0, 0x0, 0x0, 0xb, 0xe0, 0x0, 0x0, 0x0, + 0x3, 0x82, + + /* U+005D "]" */ + 0xf, 0xff, 0xff, 0x0, 0x88, 0x8d, 0xf0, 0x0, + 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, + 0xbf, 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, + 0x0, 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, + 0x0, 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, + 0xb, 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, + 0xf0, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xb, 0xf0, + 0x0, 0x0, 0xbf, 0x0, 0x88, 0x8d, 0xf0, 0xf, + 0xff, 0xff, 0x0, + + /* U+005E "^" */ + 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0xc, 0xef, + 0x40, 0x0, 0x0, 0x5f, 0x2c, 0xd0, 0x0, 0x0, + 0xda, 0x4, 0xf6, 0x0, 0x6, 0xf2, 0x0, 0xbe, + 0x0, 0xe, 0x90, 0x0, 0x3f, 0x80, 0x7f, 0x20, + 0x0, 0xa, 0xf2, + + /* U+005F "_" */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x84, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, + + /* U+0060 "`" */ + 0x3, 0x24, 0xfa, 0x3f, 0x92, 0xf8, 0x1f, 0x70, + 0xf6, + + /* U+0061 "a" */ + 0x5, 0xbe, 0xfe, 0xb4, 0x0, 0xcf, 0xba, 0xbf, + 0xf3, 0x3, 0x0, 0x0, 0x6f, 0xb0, 0x0, 0x0, + 0x0, 0xfd, 0x0, 0x0, 0x11, 0x1f, 0xd0, 0x3b, + 0xff, 0xff, 0xfd, 0x2f, 0xf8, 0x54, 0x4f, 0xd8, + 0xf6, 0x0, 0x0, 0xfd, 0x9f, 0x50, 0x0, 0x9f, + 0xd4, 0xff, 0x9a, 0xee, 0xed, 0x6, 0xdf, 0xe9, + 0x1c, 0xd0, + + /* U+0062 "b" */ + 0x5f, 0x60, 0x0, 0x0, 0x0, 0x5f, 0x60, 0x0, + 0x0, 0x0, 0x5f, 0x60, 0x0, 0x0, 0x0, 0x5f, + 0x60, 0x0, 0x0, 0x0, 0x5f, 0x63, 0xbf, 0xe8, + 0x0, 0x5f, 0x9f, 0xea, 0xef, 0x80, 0x5f, 0xfa, + 0x0, 0x2f, 0xf0, 0x5f, 0xb0, 0x0, 0xa, 0xf3, + 0x5f, 0x60, 0x0, 0x7, 0xf5, 0x5f, 0x60, 0x0, + 0x6, 0xf6, 0x5f, 0x60, 0x0, 0x7, 0xf5, 0x5f, + 0x60, 0x0, 0xb, 0xf2, 0x5f, 0x60, 0x0, 0x4f, + 0xb0, 0x5f, 0xea, 0x8b, 0xfe, 0x20, 0x18, 0xce, + 0xfe, 0x91, 0x0, + + /* U+0063 "c" */ + 0x0, 0x7, 0xdf, 0xfc, 0x60, 0xc, 0xfe, 0xaa, + 0xda, 0x9, 0xfa, 0x0, 0x0, 0x10, 0xfe, 0x0, + 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x5, 0xf8, + 0x0, 0x0, 0x0, 0x5f, 0x90, 0x0, 0x0, 0x2, + 0xfd, 0x0, 0x0, 0x0, 0xc, 0xf8, 0x0, 0x0, + 0x10, 0x3f, 0xfe, 0xaa, 0xda, 0x0, 0x29, 0xef, + 0xec, 0x50, + + /* U+0064 "d" */ + 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, + 0xfd, 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, + 0x0, 0xfd, 0x0, 0x4b, 0xff, 0xdf, 0xd0, 0x7f, + 0xea, 0x9d, 0xfd, 0x2f, 0xc1, 0x0, 0xf, 0xd9, + 0xf4, 0x0, 0x0, 0xfd, 0xcf, 0x0, 0x0, 0xf, + 0xdd, 0xf0, 0x0, 0x0, 0xfd, 0xcf, 0x0, 0x0, + 0xf, 0xdb, 0xf1, 0x0, 0x4, 0xfd, 0x7f, 0x70, + 0x2, 0xef, 0xd1, 0xef, 0x98, 0xfb, 0xcd, 0x2, + 0xcf, 0xe7, 0xc, 0xd0, + + /* U+0065 "e" */ + 0x0, 0x4c, 0xff, 0xb3, 0x0, 0x6, 0xfe, 0x9a, + 0xff, 0x30, 0x1f, 0xd1, 0x0, 0x3f, 0xd0, 0x7f, + 0x50, 0x0, 0xb, 0xf2, 0xbf, 0x42, 0x22, 0x29, + 0xf4, 0xcf, 0xff, 0xff, 0xff, 0xf5, 0xbf, 0x65, + 0x55, 0x55, 0x51, 0x9f, 0x40, 0x0, 0x0, 0x0, + 0x3f, 0xd1, 0x0, 0x0, 0x0, 0x9, 0xff, 0xa9, + 0x9b, 0xb0, 0x0, 0x6c, 0xff, 0xec, 0x70, + + /* U+0066 "f" */ + 0x0, 0x0, 0x3, 0xbe, 0xfe, 0x90, 0x0, 0x2, + 0xff, 0xb9, 0xaa, 0x0, 0x0, 0x9f, 0x60, 0x0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, + 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0x71, 0x99, + 0x9f, 0xf9, 0x99, 0x94, 0x0, 0x0, 0xef, 0x0, + 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0xef, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xef, + 0x0, 0x0, 0x0, + + /* U+0067 "g" */ + 0x0, 0x7, 0xdf, 0xff, 0xff, 0xb0, 0x9, 0xfc, + 0x7a, 0xff, 0xc8, 0x3, 0xfb, 0x0, 0x7, 0xf6, + 0x0, 0x6f, 0x70, 0x0, 0x3f, 0x90, 0x4, 0xf9, + 0x0, 0x5, 0xf8, 0x0, 0xd, 0xf6, 0x25, 0xef, + 0x20, 0x0, 0xef, 0xff, 0xfd, 0x40, 0x0, 0x7f, + 0x32, 0x43, 0x0, 0x0, 0x9, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xea, 0xaa, 0x97, 0x10, 0x0, + 0xef, 0xff, 0xff, 0xff, 0x30, 0xbf, 0x50, 0x0, + 0x18, 0xf9, 0xf, 0xe0, 0x0, 0x0, 0x7f, 0x80, + 0xbf, 0xd9, 0x88, 0xbf, 0xe1, 0x0, 0x8d, 0xff, + 0xfd, 0x81, 0x0, + + /* U+0068 "h" */ + 0x5f, 0x60, 0x0, 0x0, 0x5, 0xf6, 0x0, 0x0, + 0x0, 0x5f, 0x60, 0x0, 0x0, 0x5, 0xf6, 0x0, + 0x0, 0x0, 0x5f, 0x63, 0xcf, 0xd6, 0x5, 0xfa, + 0xfd, 0xaf, 0xf5, 0x5f, 0xf9, 0x0, 0x3f, 0xb5, + 0xfb, 0x0, 0x0, 0xfd, 0x5f, 0x60, 0x0, 0xe, + 0xe5, 0xf6, 0x0, 0x0, 0xee, 0x5f, 0x60, 0x0, + 0xe, 0xe5, 0xf6, 0x0, 0x0, 0xee, 0x5f, 0x60, + 0x0, 0xe, 0xe5, 0xf6, 0x0, 0x0, 0xee, 0x5f, + 0x60, 0x0, 0xe, 0xe0, + + /* U+0069 "i" */ + 0x0, 0x4, 0xeb, 0x0, 0x0, 0x0, 0x9, 0xff, + 0x10, 0x0, 0x0, 0x3, 0xea, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xff, 0x0, + 0x0, 0x7, 0x88, 0xef, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, + 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, + 0x0, 0x29, 0x99, 0xff, 0x99, 0x90, 0x3f, 0xff, + 0xff, 0xff, 0xf0, + + /* U+006A "j" */ + 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0xd, 0xfe, + 0x0, 0x0, 0x6, 0xe7, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xff, 0xff, 0xf9, 0x28, 0x88, 0x8a, 0xf9, + 0x0, 0x0, 0x3, 0xf9, 0x0, 0x0, 0x3, 0xf9, + 0x0, 0x0, 0x3, 0xf9, 0x0, 0x0, 0x3, 0xf9, + 0x0, 0x0, 0x3, 0xf9, 0x0, 0x0, 0x3, 0xf9, + 0x0, 0x0, 0x3, 0xf9, 0x0, 0x0, 0x3, 0xf9, + 0x0, 0x0, 0x3, 0xf9, 0x0, 0x0, 0x5, 0xf7, + 0x10, 0x0, 0xc, 0xf3, 0xad, 0xaa, 0xef, 0xa0, + 0x5c, 0xff, 0xd7, 0x0, + + /* U+006B "k" */ + 0x2f, 0xa0, 0x0, 0x0, 0x0, 0x2f, 0xa0, 0x0, + 0x0, 0x0, 0x2f, 0xa0, 0x0, 0x0, 0x0, 0x2f, + 0xa0, 0x0, 0x0, 0x0, 0x2f, 0xa0, 0x0, 0x3f, + 0xf3, 0x2f, 0xa0, 0x2, 0xef, 0x30, 0x2f, 0xa0, + 0x1e, 0xf4, 0x0, 0x2f, 0xa1, 0xdf, 0x50, 0x0, + 0x2f, 0xbc, 0xf5, 0x0, 0x0, 0x2f, 0xce, 0xf3, + 0x0, 0x0, 0x2f, 0xa3, 0xfe, 0x10, 0x0, 0x2f, + 0xa0, 0x6f, 0xd0, 0x0, 0x2f, 0xa0, 0x9, 0xfb, + 0x0, 0x2f, 0xa0, 0x0, 0xcf, 0x90, 0x2f, 0xa0, + 0x0, 0x1d, 0xf7, + + /* U+006C "l" */ + 0xe, 0xff, 0xff, 0x0, 0x0, 0x7, 0x88, 0xef, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, + 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, + 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, + 0x0, 0x29, 0x99, 0xff, 0x99, 0x90, 0x3f, 0xff, + 0xff, 0xff, 0xf0, + + /* U+006D "m" */ + 0x1f, 0x48, 0xfb, 0x8, 0xfb, 0x1, 0xfa, 0xd8, + 0xf9, 0xd8, 0xf6, 0x1f, 0xf3, 0x1f, 0xf4, 0xf, + 0x91, 0xfb, 0x0, 0xfc, 0x0, 0xf9, 0x1f, 0x90, + 0xf, 0x90, 0xf, 0xa1, 0xf9, 0x0, 0xf9, 0x0, + 0xfa, 0x1f, 0x90, 0xf, 0x90, 0xf, 0xa1, 0xf9, + 0x0, 0xf9, 0x0, 0xfa, 0x1f, 0x90, 0xf, 0x90, + 0xf, 0xa1, 0xf9, 0x0, 0xf9, 0x0, 0xfa, 0x1f, + 0x90, 0xf, 0x90, 0xf, 0xa0, + + /* U+006E "n" */ + 0x5f, 0x44, 0xcf, 0xd7, 0x5, 0xfb, 0xfa, 0x7d, + 0xf5, 0x5f, 0xf6, 0x0, 0x2f, 0xb5, 0xf9, 0x0, + 0x0, 0xed, 0x5f, 0x60, 0x0, 0xe, 0xe5, 0xf6, + 0x0, 0x0, 0xee, 0x5f, 0x60, 0x0, 0xe, 0xe5, + 0xf6, 0x0, 0x0, 0xee, 0x5f, 0x60, 0x0, 0xe, + 0xe5, 0xf6, 0x0, 0x0, 0xee, 0x5f, 0x60, 0x0, + 0xe, 0xe0, + + /* U+006F "o" */ + 0x0, 0x6, 0xcf, 0xfb, 0x40, 0x0, 0xa, 0xfe, + 0xab, 0xff, 0x60, 0x5, 0xfb, 0x0, 0x3, 0xff, + 0x10, 0xcf, 0x20, 0x0, 0x9, 0xf5, 0xf, 0xe0, + 0x0, 0x0, 0x5f, 0x80, 0xfc, 0x0, 0x0, 0x4, + 0xf9, 0xf, 0xe0, 0x0, 0x0, 0x5f, 0x80, 0xdf, + 0x20, 0x0, 0x9, 0xf4, 0x7, 0xfa, 0x0, 0x4, + 0xfd, 0x0, 0xc, 0xfd, 0xaa, 0xff, 0x30, 0x0, + 0x8, 0xdf, 0xea, 0x20, 0x0, + + /* U+0070 "p" */ + 0x5f, 0x44, 0xcf, 0xe8, 0x0, 0x5f, 0xaf, 0xb7, + 0xcf, 0x80, 0x5f, 0xf7, 0x0, 0xe, 0xf0, 0x5f, + 0xa0, 0x0, 0x9, 0xf3, 0x5f, 0x60, 0x0, 0x7, + 0xf5, 0x5f, 0x60, 0x0, 0x6, 0xf6, 0x5f, 0x60, + 0x0, 0x7, 0xf5, 0x5f, 0x60, 0x0, 0xb, 0xf2, + 0x5f, 0x60, 0x0, 0x4f, 0xb0, 0x5f, 0xea, 0x8a, + 0xfe, 0x20, 0x5f, 0xef, 0xfe, 0x91, 0x0, 0x5f, + 0x60, 0x0, 0x0, 0x0, 0x5f, 0x60, 0x0, 0x0, + 0x0, 0x5f, 0x60, 0x0, 0x0, 0x0, 0x5f, 0x60, + 0x0, 0x0, 0x0, + + /* U+0071 "q" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xbe, 0xfd, + 0xbc, 0x7, 0xfe, 0x99, 0xcf, 0xd2, 0xfc, 0x0, + 0x0, 0xfd, 0x9f, 0x40, 0x0, 0xf, 0xdc, 0xf0, + 0x0, 0x0, 0xfd, 0xdf, 0x0, 0x0, 0xf, 0xdc, + 0xf0, 0x0, 0x0, 0xfd, 0xbf, 0x20, 0x0, 0x5f, + 0xd7, 0xf9, 0x0, 0x4f, 0xfd, 0x1e, 0xfb, 0xbf, + 0x9d, 0xd0, 0x3c, 0xfd, 0x70, 0xed, 0x0, 0x0, + 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfd, 0x0, + 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfd, + + /* U+0072 "r" */ + 0xfb, 0x7, 0xdf, 0xc3, 0xf, 0xcb, 0xf8, 0x8f, + 0xe1, 0xff, 0xe2, 0x0, 0x8f, 0x5f, 0xf3, 0x0, + 0x5, 0xf7, 0xfd, 0x0, 0x0, 0x2, 0x1f, 0xd0, + 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, 0xf, + 0xd0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, 0x0, + 0xf, 0xd0, 0x0, 0x0, 0x0, 0xfd, 0x0, 0x0, + 0x0, 0x0, + + /* U+0073 "s" */ + 0x0, 0x5c, 0xff, 0xec, 0x10, 0x7f, 0xea, 0x9a, + 0xd1, 0xe, 0xe0, 0x0, 0x0, 0x0, 0xef, 0x10, + 0x0, 0x0, 0x8, 0xff, 0x83, 0x0, 0x0, 0x6, + 0xef, 0xfd, 0x50, 0x0, 0x0, 0x39, 0xff, 0x50, + 0x0, 0x0, 0x4, 0xfb, 0x0, 0x0, 0x0, 0x3f, + 0xb2, 0xfb, 0xa9, 0xbf, 0xf3, 0x1b, 0xef, 0xfe, + 0xa3, 0x0, + + /* U+0074 "t" */ + 0x0, 0x0, 0x32, 0x0, 0x0, 0x0, 0x7, 0xf5, + 0x0, 0x0, 0x0, 0x7, 0xf5, 0x0, 0x0, 0x0, + 0x7, 0xf5, 0x0, 0x0, 0x5f, 0xff, 0xff, 0xff, + 0xff, 0x39, 0x9c, 0xfb, 0x99, 0x98, 0x0, 0x7, + 0xf5, 0x0, 0x0, 0x0, 0x7, 0xf5, 0x0, 0x0, + 0x0, 0x7, 0xf5, 0x0, 0x0, 0x0, 0x7, 0xf5, + 0x0, 0x0, 0x0, 0x7, 0xf5, 0x0, 0x0, 0x0, + 0x6, 0xf5, 0x0, 0x0, 0x0, 0x4, 0xfb, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0xda, 0xac, 0x0, 0x0, + 0x1a, 0xef, 0xfb, + + /* U+0075 "u" */ + 0x5f, 0x60, 0x0, 0xe, 0xe5, 0xf6, 0x0, 0x0, + 0xee, 0x5f, 0x60, 0x0, 0xe, 0xe5, 0xf6, 0x0, + 0x0, 0xee, 0x5f, 0x60, 0x0, 0xe, 0xe5, 0xf6, + 0x0, 0x0, 0xee, 0x5f, 0x60, 0x0, 0xe, 0xe4, + 0xf7, 0x0, 0x1, 0xfe, 0x2f, 0xa0, 0x1, 0xcf, + 0xe0, 0xcf, 0x97, 0xdd, 0xde, 0x2, 0xbf, 0xea, + 0x1b, 0xe0, + + /* U+0076 "v" */ + 0x2f, 0xd0, 0x0, 0x0, 0x5f, 0x90, 0xcf, 0x30, + 0x0, 0xa, 0xf3, 0x6, 0xf9, 0x0, 0x0, 0xfd, + 0x0, 0x1f, 0xe0, 0x0, 0x5f, 0x80, 0x0, 0xaf, + 0x40, 0xb, 0xf2, 0x0, 0x5, 0xf9, 0x1, 0xfc, + 0x0, 0x0, 0xe, 0xe0, 0x6f, 0x60, 0x0, 0x0, + 0x9f, 0x4b, 0xf1, 0x0, 0x0, 0x3, 0xfa, 0xfa, + 0x0, 0x0, 0x0, 0xd, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x7f, 0xe0, 0x0, 0x0, + + /* U+0077 "w" */ + 0x8f, 0x20, 0x0, 0x0, 0xa, 0xf1, 0x6f, 0x40, + 0x0, 0x0, 0xc, 0xf0, 0x4f, 0x60, 0x3, 0x10, + 0xd, 0xd0, 0x2f, 0x80, 0x2f, 0xa0, 0xf, 0xb0, + 0xf, 0xa0, 0x6f, 0xf0, 0x1f, 0x90, 0xe, 0xc0, + 0xbd, 0xf4, 0x2f, 0x60, 0xc, 0xd0, 0xf6, 0xea, + 0x4f, 0x40, 0x9, 0xf5, 0xf1, 0x9f, 0x6f, 0x20, + 0x7, 0xfb, 0xc0, 0x4f, 0xcf, 0x0, 0x5, 0xff, + 0x70, 0xf, 0xfe, 0x0, 0x3, 0xff, 0x20, 0xa, + 0xfc, 0x0, + + /* U+0078 "x" */ + 0xb, 0xf8, 0x0, 0x0, 0xcf, 0x60, 0x1f, 0xf2, + 0x0, 0x6f, 0xb0, 0x0, 0x5f, 0xc0, 0x1e, 0xe1, + 0x0, 0x0, 0xaf, 0x6a, 0xf4, 0x0, 0x0, 0x1, + 0xef, 0xf9, 0x0, 0x0, 0x0, 0x7, 0xff, 0x10, + 0x0, 0x0, 0x1, 0xef, 0xf9, 0x0, 0x0, 0x0, + 0xbf, 0x5c, 0xf5, 0x0, 0x0, 0x7f, 0xa0, 0x2f, + 0xf2, 0x0, 0x3f, 0xe1, 0x0, 0x7f, 0xc0, 0xd, + 0xf5, 0x0, 0x0, 0xcf, 0x80, + + /* U+0079 "y" */ + 0x2f, 0xe0, 0x0, 0x0, 0x5f, 0x90, 0xbf, 0x40, + 0x0, 0xa, 0xf3, 0x5, 0xfa, 0x0, 0x0, 0xfd, + 0x0, 0xe, 0xf0, 0x0, 0x6f, 0x80, 0x0, 0x9f, + 0x60, 0xb, 0xf2, 0x0, 0x3, 0xfc, 0x1, 0xfc, + 0x0, 0x0, 0xc, 0xf2, 0x6f, 0x60, 0x0, 0x0, + 0x6f, 0x7c, 0xf0, 0x0, 0x0, 0x1, 0xfd, 0xfa, + 0x0, 0x0, 0x0, 0xa, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x5f, 0xd0, 0x0, 0x0, 0x0, 0xb, 0xf6, + 0x0, 0x0, 0x0, 0x7, 0xfd, 0x0, 0x0, 0x4, + 0xad, 0xfe, 0x20, 0x0, 0x0, 0x6f, 0xe9, 0x10, + 0x0, 0x0, 0x0, + + /* U+007A "z" */ + 0x2f, 0xff, 0xff, 0xff, 0xa1, 0x99, 0x99, 0x9d, + 0xf8, 0x0, 0x0, 0x3, 0xfd, 0x0, 0x0, 0x0, + 0xdf, 0x30, 0x0, 0x0, 0x9f, 0x70, 0x0, 0x0, + 0x5f, 0xb0, 0x0, 0x0, 0x1e, 0xe1, 0x0, 0x0, + 0xc, 0xf4, 0x0, 0x0, 0x7, 0xf9, 0x0, 0x0, + 0x2, 0xff, 0x99, 0x99, 0x99, 0x5f, 0xff, 0xff, + 0xff, 0xf0, + + /* U+007B "{" */ + 0x0, 0x0, 0x2b, 0xef, 0x30, 0x0, 0x1e, 0xfb, + 0x81, 0x0, 0x5, 0xf8, 0x0, 0x0, 0x0, 0x7f, + 0x30, 0x0, 0x0, 0x7, 0xf3, 0x0, 0x0, 0x0, + 0x7f, 0x30, 0x0, 0x0, 0xa, 0xf1, 0x0, 0x2, + 0x8b, 0xf8, 0x0, 0x0, 0x5f, 0xfb, 0x20, 0x0, + 0x0, 0x4, 0xfd, 0x0, 0x0, 0x0, 0x9, 0xf2, + 0x0, 0x0, 0x0, 0x7f, 0x30, 0x0, 0x0, 0x7, + 0xf3, 0x0, 0x0, 0x0, 0x7f, 0x30, 0x0, 0x0, + 0x7, 0xf3, 0x0, 0x0, 0x0, 0x7f, 0x40, 0x0, + 0x0, 0x4, 0xf9, 0x0, 0x0, 0x0, 0xd, 0xfb, + 0x81, 0x0, 0x0, 0x1a, 0xef, 0x30, + + /* U+007C "|" */ + 0x1f, 0x91, 0xf9, 0x1f, 0x91, 0xf9, 0x1f, 0x91, + 0xf9, 0x1f, 0x91, 0xf9, 0x1f, 0x91, 0xf9, 0x1f, + 0x91, 0xf9, 0x1f, 0x91, 0xf9, 0x1f, 0x91, 0xf9, + 0x1f, 0x91, 0xf9, 0x1f, 0x91, 0xf9, 0x1f, 0x91, + 0xf9, + + /* U+007D "}" */ + 0xaf, 0xd7, 0x0, 0x0, 0x59, 0xef, 0x70, 0x0, + 0x0, 0x1e, 0xd0, 0x0, 0x0, 0xb, 0xf0, 0x0, + 0x0, 0xb, 0xf0, 0x0, 0x0, 0xa, 0xf0, 0x0, + 0x0, 0x9, 0xf3, 0x0, 0x0, 0x2, 0xef, 0x97, + 0x0, 0x0, 0x5e, 0xfe, 0x0, 0x4, 0xf9, 0x10, + 0x0, 0x9, 0xf1, 0x0, 0x0, 0xa, 0xf0, 0x0, + 0x0, 0xa, 0xf0, 0x0, 0x0, 0xa, 0xf0, 0x0, + 0x0, 0xa, 0xf0, 0x0, 0x0, 0xb, 0xf0, 0x0, + 0x0, 0x1f, 0xd0, 0x0, 0x59, 0xef, 0x60, 0x0, + 0xaf, 0xd6, 0x0, 0x0, + + /* U+007E "~" */ + 0x0, 0x7a, 0x70, 0x0, 0x0, 0x10, 0x9f, 0xff, + 0xc0, 0x0, 0xcd, 0x1f, 0xb1, 0x8f, 0xb0, 0xf, + 0xb3, 0xf6, 0x0, 0x9f, 0xed, 0xf4, 0x16, 0x20, + 0x0, 0x7e, 0xe7, 0x0, + + /* U+007F "" */ + + /* U+4E2D "中" */ + 0x0, 0x0, 0x0, 0x0, 0x5, 0x30, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf9, 0x1f, 0xc7, 0x77, 0x77, 0x8f, 0xd7, 0x77, + 0x77, 0x8f, 0x91, 0xf9, 0x0, 0x0, 0x1, 0xfa, + 0x0, 0x0, 0x1, 0xf9, 0x1f, 0x90, 0x0, 0x0, + 0x1f, 0xa0, 0x0, 0x0, 0x1f, 0x91, 0xf9, 0x0, + 0x0, 0x1, 0xfa, 0x0, 0x0, 0x1, 0xf9, 0x1f, + 0x90, 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x1f, + 0x91, 0xfc, 0x77, 0x77, 0x78, 0xfd, 0x77, 0x77, + 0x78, 0xf9, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x91, 0xfa, 0x0, 0x0, 0x1, + 0xfa, 0x0, 0x0, 0x1, 0xf9, 0x5, 0x30, 0x0, + 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x5, 0x30, 0x0, + 0x0, 0x0, 0x1, 0xfa, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x0, 0x0, + + /* U+6587 "æ–‡" */ + 0x0, 0x0, 0x0, 0x0, 0x3, 0x30, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x9, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1e, 0x70, 0x0, 0x0, + 0x0, 0x0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x15, 0x99, 0x9d, 0xf9, + 0x99, 0x99, 0x99, 0x9c, 0xfb, 0x99, 0x91, 0x0, + 0x0, 0x7f, 0x20, 0x0, 0x0, 0x0, 0xaf, 0x10, + 0x0, 0x0, 0x0, 0x3, 0xf6, 0x0, 0x0, 0x0, + 0xe, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xc0, + 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0x30, 0x0, 0x0, 0x9f, 0x20, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xfb, 0x0, 0x0, 0x1f, + 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf5, + 0x0, 0xb, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xd, 0xe2, 0x6, 0xf9, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xd6, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, + 0xfe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1a, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0x8f, 0xfb, 0x5e, 0xfd, 0x60, + 0x0, 0x0, 0x0, 0x0, 0x39, 0xff, 0xd5, 0x0, + 0x19, 0xff, 0xfa, 0x40, 0x0, 0x28, 0xdf, 0xfd, + 0x60, 0x0, 0x0, 0x2, 0x9f, 0xff, 0xfa, 0x5, + 0xff, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, + 0xdf, 0x70, 0x5, 0x10, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x30, 0x0 +}; + + +static const sgl_font_table_t sgl_ascii_consolas23_tab[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 185, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 185, .box_w = 4, .box_h = 15, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 30, .adv_w = 185, .box_w = 7, .box_h = 6, .ofs_x = 2, .ofs_y = 9}, + {.bitmap_index = 51, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 135, .adv_w = 185, .box_w = 10, .box_h = 19, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 230, .adv_w = 185, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 320, .adv_w = 185, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 410, .adv_w = 185, .box_w = 3, .box_h = 6, .ofs_x = 4, .ofs_y = 9}, + {.bitmap_index = 419, .adv_w = 185, .box_w = 6, .box_h = 22, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 485, .adv_w = 185, .box_w = 7, .box_h = 22, .ofs_x = 2, .ofs_y = -5}, + {.bitmap_index = 562, .adv_w = 185, .box_w = 9, .box_h = 10, .ofs_x = 1, .ofs_y = 5}, + {.bitmap_index = 607, .adv_w = 185, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 668, .adv_w = 185, .box_w = 6, .box_h = 8, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 692, .adv_w = 185, .box_w = 7, .box_h = 2, .ofs_x = 2, .ofs_y = 5}, + {.bitmap_index = 699, .adv_w = 185, .box_w = 5, .box_h = 4, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 709, .adv_w = 185, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 799, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 876, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 946, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1016, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1086, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1163, .adv_w = 185, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1226, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1296, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1366, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1436, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1506, .adv_w = 185, .box_w = 4, .box_h = 11, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 1528, .adv_w = 185, .box_w = 6, .box_h = 15, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 1573, .adv_w = 185, .box_w = 9, .box_h = 13, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 1632, .adv_w = 185, .box_w = 10, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 1662, .adv_w = 185, .box_w = 9, .box_h = 13, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 1721, .adv_w = 185, .box_w = 7, .box_h = 15, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 1774, .adv_w = 185, .box_w = 12, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 1888, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1972, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2042, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2119, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2189, .adv_w = 185, .box_w = 8, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2245, .adv_w = 185, .box_w = 8, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2301, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2378, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2448, .adv_w = 185, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2511, .adv_w = 185, .box_w = 8, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2567, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2637, .adv_w = 185, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2700, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2784, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2854, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2931, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3001, .adv_w = 185, .box_w = 12, .box_h = 18, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 3109, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3179, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3249, .adv_w = 185, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3326, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3396, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3480, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3564, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3648, .adv_w = 185, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3732, .adv_w = 185, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3802, .adv_w = 185, .box_w = 6, .box_h = 19, .ofs_x = 3, .ofs_y = -4}, + {.bitmap_index = 3859, .adv_w = 185, .box_w = 10, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3949, .adv_w = 185, .box_w = 7, .box_h = 19, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 4016, .adv_w = 185, .box_w = 10, .box_h = 7, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 4051, .adv_w = 185, .box_w = 12, .box_h = 2, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4063, .adv_w = 86, .box_w = 3, .box_h = 6, .ofs_x = 1, .ofs_y = 12}, + {.bitmap_index = 4072, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4122, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4197, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4247, .adv_w = 185, .box_w = 9, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4315, .adv_w = 185, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4370, .adv_w = 185, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4453, .adv_w = 185, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4536, .adv_w = 185, .box_w = 9, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4604, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4679, .adv_w = 185, .box_w = 8, .box_h = 19, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 4755, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4830, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4905, .adv_w = 185, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4966, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5016, .adv_w = 185, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5077, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 5152, .adv_w = 185, .box_w = 9, .box_h = 16, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 5224, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5274, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5324, .adv_w = 185, .box_w = 10, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5399, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5449, .adv_w = 185, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5510, .adv_w = 185, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5576, .adv_w = 185, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5637, .adv_w = 185, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 5720, .adv_w = 185, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5770, .adv_w = 185, .box_w = 9, .box_h = 19, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 5856, .adv_w = 185, .box_w = 3, .box_h = 22, .ofs_x = 4, .ofs_y = -4}, + {.bitmap_index = 5889, .adv_w = 185, .box_w = 8, .box_h = 19, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 5965, .adv_w = 185, .box_w = 11, .box_h = 5, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 5993, .adv_w = 185, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5993, .adv_w = 336, .box_w = 19, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 6193, .adv_w = 336, .box_w = 21, .box_h = 21, .ofs_x = 0, .ofs_y = -3} +}; + +static const uint32_t unicode_list_1[] = { + 0x0, 0x175a +}; + +static const sgl_font_unicode_t consolas23_unicode[] = { + { .offset = 32, .len = 96, .list = NULL, .tab_offset = 1, }, + { .offset = 20013, .len = 2, .list = unicode_list_1, .tab_offset = 97, }, +}; + +const sgl_font_t consolas23 = { + .bitmap = sgl_ascii_consolas23_bitmap, + .table = sgl_ascii_consolas23_tab, + .font_table_size = SGL_ARRAY_SIZE(sgl_ascii_consolas23_tab), + .font_height = 23, + .base_line = 5, + .bpp = 4, + .unicode = consolas23_unicode, + .unicode_num = 2, +}; + + +#endif // !CONFIG_SGL_FONT_CONSOLAS23 diff --git a/User/system/sgl/fonts/sgl_ascii_consolas24.c b/User/system/sgl/fonts/sgl_ascii_consolas24.c new file mode 100644 index 0000000..308c67c --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_consolas24.c @@ -0,0 +1,1239 @@ +/* source/fonts/sgl_ascii_consolas24.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#if (CONFIG_SGL_FONT_CONSOLAS24) + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static const uint8_t glyph_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0x1f, 0xf2, 0x1f, 0xf1, 0xf, 0xf1, 0xf, 0xf0, + 0xf, 0xf0, 0xf, 0xf0, 0xe, 0xf0, 0xe, 0xf0, + 0xd, 0xe0, 0xd, 0xe0, 0x7, 0x80, 0x0, 0x0, + 0xa, 0xa0, 0x5f, 0xf6, 0x1d, 0xd1, + + /* U+0022 "\"" */ + 0x3f, 0xf1, 0xf, 0xf4, 0x2f, 0xf0, 0xf, 0xf3, + 0x1f, 0xf0, 0xe, 0xf2, 0xf, 0xe0, 0xd, 0xf1, + 0xf, 0xd0, 0xc, 0xf0, 0x0, 0x0, 0x0, 0x0, + + /* U+0023 "#" */ + 0x0, 0x4, 0xf4, 0x0, 0xfa, 0x0, 0x0, 0x6, + 0xf2, 0x1, 0xf8, 0x0, 0x0, 0x8, 0xf0, 0x3, + 0xf6, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xfa, + 0x6, 0x6d, 0xe6, 0x6a, 0xf8, 0x64, 0x0, 0xd, + 0xc0, 0x7, 0xf1, 0x0, 0x0, 0xe, 0xa0, 0x9, + 0xf0, 0x0, 0x0, 0xf, 0x90, 0xa, 0xe0, 0x0, + 0x1, 0x2f, 0x91, 0x1c, 0xd1, 0x10, 0x8f, 0xff, + 0xff, 0xff, 0xff, 0xf1, 0x24, 0x7f, 0x74, 0x4f, + 0xb4, 0x40, 0x0, 0x6f, 0x30, 0xf, 0x80, 0x0, + 0x0, 0x7f, 0x10, 0x2f, 0x60, 0x0, 0x0, 0x9f, + 0x0, 0x4f, 0x50, 0x0, + + /* U+0024 "$" */ + 0x0, 0x0, 0xb, 0xd0, 0x0, 0x0, 0x0, 0xd, + 0xb0, 0x0, 0x0, 0x7c, 0xff, 0xfd, 0x90, 0xc, + 0xfc, 0x9f, 0xcb, 0xb0, 0x7f, 0x90, 0x4f, 0x40, + 0x0, 0xaf, 0x50, 0x6f, 0x20, 0x0, 0x8f, 0xb0, + 0x8f, 0x0, 0x0, 0x1d, 0xfe, 0xde, 0x0, 0x0, + 0x1, 0x9f, 0xff, 0xa2, 0x0, 0x0, 0x1, 0xff, + 0xff, 0x70, 0x0, 0x1, 0xf7, 0x5e, 0xf5, 0x0, + 0x3, 0xf5, 0x5, 0xfb, 0x0, 0x5, 0xf3, 0x5, + 0xfb, 0x53, 0x17, 0xf1, 0x3d, 0xf7, 0xdf, 0xff, + 0xff, 0xff, 0xc0, 0x7c, 0xef, 0xff, 0xc7, 0x0, + 0x0, 0xd, 0xb0, 0x0, 0x0, 0x0, 0xf, 0x80, + 0x0, 0x0, 0x0, 0x3, 0x10, 0x0, 0x0, + + /* U+0025 "%" */ + 0x5, 0xdf, 0xb2, 0x0, 0x3, 0xf8, 0x2f, 0x94, + 0xec, 0x0, 0xd, 0xd0, 0x8f, 0x10, 0x7f, 0x10, + 0x8f, 0x30, 0x8f, 0x0, 0x7f, 0x13, 0xf9, 0x0, + 0x5f, 0x72, 0xdd, 0xd, 0xd0, 0x0, 0xb, 0xff, + 0xe3, 0x8f, 0x40, 0x0, 0x0, 0x23, 0x3, 0xf9, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x8f, 0x40, 0x0, 0x0, 0x0, 0x2, + 0xf9, 0x1b, 0xff, 0x90, 0x0, 0xc, 0xe0, 0xaf, + 0x68, 0xf6, 0x0, 0x7f, 0x40, 0xf9, 0x0, 0xfa, + 0x2, 0xfa, 0x0, 0xf9, 0x0, 0xf9, 0xc, 0xe1, + 0x0, 0xbe, 0x48, 0xf4, 0x7f, 0x50, 0x0, 0x1b, + 0xfd, 0x60, + + /* U+0026 "&" */ + 0x0, 0x6, 0xdf, 0xd8, 0x0, 0x0, 0x0, 0x7, + 0xfd, 0x9d, 0xf9, 0x0, 0x0, 0x0, 0xff, 0x10, + 0x1f, 0xf0, 0x0, 0x0, 0x2f, 0xc0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xff, 0x0, 0x3f, 0xc0, 0x0, + 0x0, 0xb, 0xf8, 0x4e, 0xf3, 0x0, 0x0, 0x0, + 0x2f, 0xff, 0xd3, 0x0, 0x0, 0x0, 0x7, 0xff, + 0xf2, 0x0, 0x45, 0x0, 0x7, 0xfc, 0x9f, 0xd0, + 0xf, 0xf0, 0x1, 0xfe, 0x10, 0xcf, 0xb0, 0xfd, + 0x0, 0x4f, 0xa0, 0x1, 0xef, 0xbf, 0x90, 0x5, + 0xfa, 0x0, 0x3, 0xff, 0xf3, 0x0, 0x2f, 0xe1, + 0x0, 0x9, 0xff, 0x20, 0x0, 0x8f, 0xe8, 0x7b, + 0xff, 0xfd, 0x0, 0x0, 0x6d, 0xff, 0xc6, 0xc, + 0xfb, 0x0, + + /* U+0027 "'" */ + 0x2f, 0xf3, 0x1f, 0xf3, 0xf, 0xf2, 0xf, 0xf1, + 0xe, 0xf0, 0x0, 0x0, + + /* U+0028 "(" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xa0, 0x0, + 0x4, 0xfd, 0x10, 0x2, 0xee, 0x10, 0x0, 0xbf, + 0x40, 0x0, 0x5f, 0xa0, 0x0, 0xc, 0xf2, 0x0, + 0x2, 0xfc, 0x0, 0x0, 0x7f, 0x70, 0x0, 0xa, + 0xf4, 0x0, 0x0, 0xbf, 0x20, 0x0, 0xc, 0xf2, + 0x0, 0x0, 0xbf, 0x30, 0x0, 0x9, 0xf6, 0x0, + 0x0, 0x5f, 0xa0, 0x0, 0x1, 0xff, 0x0, 0x0, + 0x9, 0xf6, 0x0, 0x0, 0x1f, 0xe1, 0x0, 0x0, + 0x7f, 0xa0, 0x0, 0x0, 0xbf, 0x70, 0x0, 0x0, + 0xcf, 0x10, 0x0, 0x0, 0x30, + + /* U+0029 ")" */ + 0x0, 0x0, 0x0, 0x0, 0x96, 0x0, 0x0, 0xc, + 0xf5, 0x0, 0x0, 0x1e, 0xf3, 0x0, 0x0, 0x3f, + 0xd0, 0x0, 0x0, 0x9f, 0x70, 0x0, 0x1, 0xfe, + 0x0, 0x0, 0xb, 0xf4, 0x0, 0x0, 0x6f, 0x80, + 0x0, 0x3, 0xfb, 0x0, 0x0, 0x1f, 0xd0, 0x0, + 0x1, 0xfd, 0x0, 0x0, 0x1f, 0xb0, 0x0, 0x4, + 0xfa, 0x0, 0x0, 0x8f, 0x60, 0x0, 0xd, 0xf1, + 0x0, 0x4, 0xfa, 0x0, 0x0, 0xdf, 0x20, 0x0, + 0x8f, 0x70, 0x0, 0x5f, 0xb0, 0x0, 0xe, 0xc1, + 0x0, 0x0, 0x21, 0x0, 0x0, + + /* U+002A "*" */ + 0x0, 0x0, 0xac, 0x0, 0x0, 0x2, 0x0, 0x9b, + 0x0, 0x20, 0xe, 0xa1, 0x8a, 0x1a, 0xf1, 0x4, + 0xce, 0xbc, 0xed, 0x50, 0x0, 0x7, 0xff, 0x80, + 0x0, 0x2, 0xaf, 0xcd, 0xfb, 0x30, 0x1f, 0xc2, + 0x8a, 0x1b, 0xf1, 0x3, 0x0, 0x9b, 0x0, 0x30, + 0x0, 0x0, 0xac, 0x0, 0x0, 0x0, 0x0, 0x11, + 0x0, 0x0, + + /* U+002B "+" */ + 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, + 0xa, 0xaa, 0xaf, 0xfa, 0xaa, 0xa1, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xf3, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x50, + 0x0, 0x0, + + /* U+002C "," */ + 0x0, 0x19, 0x70, 0x0, 0x8f, 0xf7, 0x0, 0x5f, + 0xfb, 0x0, 0xc, 0xfa, 0x0, 0xc, 0xf6, 0x14, + 0xaf, 0xc0, 0x7f, 0xf9, 0x0, 0x23, 0x0, 0x0, + + /* U+002D "-" */ + 0x1c, 0xcc, 0xcc, 0xc3, 0x2f, 0xff, 0xff, 0xf4, + + /* U+002E "." */ + 0x7, 0x70, 0x9f, 0xf8, 0xcf, 0xfa, 0x4e, 0xd3, + + /* U+002F "/" */ + 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0x8f, 0x30, 0x0, 0x0, 0x0, 0x3, 0xf9, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, 0x0, + 0x0, 0x8f, 0x40, 0x0, 0x0, 0x0, 0x3, 0xf9, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x8f, 0x40, 0x0, 0x0, 0x0, 0x2, + 0xf9, 0x0, 0x0, 0x0, 0x0, 0xc, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x7f, 0x40, 0x0, 0x0, 0x0, + 0x2, 0xfa, 0x0, 0x0, 0x0, 0x0, 0xc, 0xe1, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0x50, 0x0, 0x0, + 0x0, 0x0, + + /* U+0030 "0" */ + 0x0, 0x3, 0xbe, 0xfc, 0x60, 0x0, 0x0, 0x5f, + 0xfa, 0xaf, 0xf9, 0x0, 0x1, 0xfe, 0x20, 0x1, + 0xef, 0x40, 0x8, 0xf7, 0x0, 0x0, 0x6f, 0xa0, + 0xc, 0xf1, 0x0, 0x2, 0xcf, 0xe0, 0xf, 0xf0, + 0x0, 0x5e, 0xff, 0xf1, 0xf, 0xd0, 0x9, 0xfd, + 0x3c, 0xf2, 0xf, 0xd2, 0xcf, 0x90, 0xc, 0xf2, + 0xf, 0xff, 0xe5, 0x0, 0xd, 0xf0, 0xd, 0xfb, + 0x10, 0x0, 0xf, 0xe0, 0x9, 0xf7, 0x0, 0x0, + 0x5f, 0x90, 0x2, 0xfe, 0x20, 0x1, 0xef, 0x20, + 0x0, 0x8f, 0xfa, 0xaf, 0xf7, 0x0, 0x0, 0x5, + 0xcf, 0xfc, 0x40, 0x0, + + /* U+0031 "1" */ + 0x0, 0x4, 0xcf, 0x90, 0x0, 0x3, 0xbf, 0xff, + 0x90, 0x0, 0x5f, 0xfa, 0x9f, 0x90, 0x0, 0x1a, + 0x20, 0x8f, 0x90, 0x0, 0x0, 0x0, 0x8f, 0x90, + 0x0, 0x0, 0x0, 0x8f, 0x90, 0x0, 0x0, 0x0, + 0x8f, 0x90, 0x0, 0x0, 0x0, 0x8f, 0x90, 0x0, + 0x0, 0x0, 0x8f, 0x90, 0x0, 0x0, 0x0, 0x8f, + 0x90, 0x0, 0x0, 0x0, 0x8f, 0x90, 0x0, 0x0, + 0x0, 0x8f, 0x90, 0x0, 0x1c, 0xcc, 0xef, 0xec, + 0xc8, 0x1f, 0xff, 0xff, 0xff, 0xfb, + + /* U+0032 "2" */ + 0x0, 0x7d, 0xff, 0xb2, 0x0, 0x1d, 0xfd, 0xbd, + 0xff, 0x40, 0xb, 0x60, 0x0, 0x8f, 0xc0, 0x0, + 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, + 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, + 0x0, 0xbf, 0x50, 0x0, 0x0, 0x8, 0xfa, 0x0, + 0x0, 0x0, 0x8f, 0xc0, 0x0, 0x0, 0x8, 0xfc, + 0x0, 0x0, 0x0, 0x8f, 0xb0, 0x0, 0x0, 0x9, + 0xfb, 0x0, 0x0, 0x0, 0x5f, 0xfc, 0xcc, 0xcc, + 0xca, 0x6f, 0xff, 0xff, 0xff, 0xfd, + + /* U+0033 "3" */ + 0x7, 0xce, 0xfe, 0xb3, 0x0, 0xd, 0xdb, 0xad, + 0xff, 0x40, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, + 0x0, 0x0, 0x2f, 0xd0, 0x0, 0x0, 0x0, 0x4f, + 0xa0, 0x0, 0x0, 0x4, 0xee, 0x20, 0x0, 0x8f, + 0xff, 0xe3, 0x0, 0x0, 0x48, 0x9b, 0xff, 0x70, + 0x0, 0x0, 0x0, 0x1d, 0xf4, 0x0, 0x0, 0x0, + 0x7, 0xf8, 0x0, 0x0, 0x0, 0x8, 0xf7, 0x0, + 0x0, 0x0, 0x3f, 0xf1, 0x3c, 0xaa, 0xad, 0xff, + 0x50, 0x3e, 0xff, 0xfc, 0x81, 0x0, + + /* U+0034 "4" */ + 0x0, 0x0, 0x0, 0xdf, 0xf2, 0x0, 0x0, 0x0, + 0x8, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x2f, 0xcc, + 0xf2, 0x0, 0x0, 0x0, 0xcf, 0x2c, 0xf2, 0x0, + 0x0, 0x6, 0xf7, 0xc, 0xf2, 0x0, 0x0, 0x1f, + 0xc0, 0xc, 0xf2, 0x0, 0x0, 0xbf, 0x30, 0xc, + 0xf2, 0x0, 0x5, 0xf8, 0x0, 0xc, 0xf2, 0x0, + 0x1e, 0xd0, 0x0, 0xc, 0xf2, 0x0, 0x7f, 0xca, + 0xaa, 0xae, 0xfa, 0xa5, 0x8f, 0xff, 0xff, 0xff, + 0xff, 0xf8, 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, + 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, 0x0, + 0x0, 0xc, 0xf2, 0x0, + + /* U+0035 "5" */ + 0xd, 0xff, 0xff, 0xff, 0xb0, 0xd, 0xfa, 0xaa, + 0xaa, 0x70, 0xd, 0xe0, 0x0, 0x0, 0x0, 0xd, + 0xe0, 0x0, 0x0, 0x0, 0xd, 0xe0, 0x0, 0x0, + 0x0, 0xd, 0xf9, 0x97, 0x40, 0x0, 0xd, 0xff, + 0xff, 0xfe, 0x30, 0x0, 0x0, 0x13, 0xaf, 0xe1, + 0x0, 0x0, 0x0, 0xc, 0xf5, 0x0, 0x0, 0x0, + 0x9, 0xf6, 0x0, 0x0, 0x0, 0xc, 0xf4, 0x0, + 0x0, 0x0, 0x8f, 0xd0, 0x1c, 0xaa, 0xbe, 0xfd, + 0x20, 0x1e, 0xff, 0xec, 0x60, 0x0, + + /* U+0036 "6" */ + 0x0, 0x2, 0x8c, 0xff, 0xe0, 0x0, 0x6f, 0xfd, + 0xba, 0x90, 0x4, 0xfd, 0x30, 0x0, 0x0, 0xd, + 0xe1, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, + 0x0, 0x7f, 0x89, 0xdf, 0xea, 0x20, 0x9f, 0xfe, + 0x98, 0xcf, 0xf2, 0xaf, 0x70, 0x0, 0x8, 0xfa, + 0xaf, 0x40, 0x0, 0x1, 0xfe, 0x9f, 0x60, 0x0, + 0x0, 0xff, 0x6f, 0x90, 0x0, 0x2, 0xfd, 0x1f, + 0xf2, 0x0, 0xa, 0xf7, 0x7, 0xff, 0xa9, 0xdf, + 0xb0, 0x0, 0x5c, 0xff, 0xc6, 0x0, + + /* U+0037 "7" */ + 0xcf, 0xff, 0xff, 0xff, 0xfc, 0x9c, 0xcc, 0xcc, + 0xcc, 0xfb, 0x0, 0x0, 0x0, 0x8, 0xf6, 0x0, + 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x8f, + 0x60, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, + 0x8, 0xf7, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, + 0x0, 0x0, 0x8f, 0x80, 0x0, 0x0, 0x1, 0xff, + 0x10, 0x0, 0x0, 0x8, 0xf8, 0x0, 0x0, 0x0, + 0x1f, 0xf1, 0x0, 0x0, 0x0, 0x8f, 0x90, 0x0, + 0x0, 0x1, 0xff, 0x10, 0x0, 0x0, + + /* U+0038 "8" */ + 0x0, 0x6c, 0xff, 0xd9, 0x10, 0xa, 0xfd, 0x99, + 0xdf, 0xe1, 0x4f, 0xc0, 0x0, 0xa, 0xf6, 0x6f, + 0x80, 0x0, 0x7, 0xf7, 0x3f, 0xe1, 0x0, 0xc, + 0xf3, 0x9, 0xfe, 0x74, 0xdf, 0x80, 0x0, 0x6f, + 0xff, 0xf5, 0x0, 0x1, 0xbf, 0xde, 0xfe, 0x40, + 0x1e, 0xf7, 0x0, 0x8f, 0xf3, 0x8f, 0x90, 0x0, + 0x8, 0xfa, 0xaf, 0x50, 0x0, 0x4, 0xfc, 0x9f, + 0xb0, 0x0, 0x9, 0xf9, 0x2e, 0xfe, 0xaa, 0xdf, + 0xe1, 0x1, 0x9d, 0xff, 0xc7, 0x10, + + /* U+0039 "9" */ + 0x0, 0x6c, 0xff, 0xb4, 0x0, 0xb, 0xfd, 0x9a, + 0xef, 0x60, 0x7f, 0xb0, 0x0, 0x1e, 0xf0, 0xcf, + 0x30, 0x0, 0x8, 0xf6, 0xef, 0x10, 0x0, 0x4, + 0xf9, 0xcf, 0x40, 0x0, 0x3, 0xfb, 0x7f, 0xd3, + 0x1, 0x5b, 0xfb, 0xa, 0xff, 0xff, 0xfd, 0xfa, + 0x0, 0x37, 0x76, 0x24, 0xf8, 0x0, 0x0, 0x0, + 0x8, 0xf4, 0x0, 0x0, 0x0, 0x1e, 0xe0, 0x0, + 0x0, 0x4, 0xdf, 0x50, 0xa, 0xab, 0xef, 0xf6, + 0x0, 0x1f, 0xfe, 0xc7, 0x10, 0x0, + + /* U+003A ":" */ + 0x2d, 0xd3, 0x8f, 0xfa, 0x4f, 0xf6, 0x2, 0x30, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, + 0x4f, 0xf5, 0x8f, 0xfa, 0x2d, 0xe3, + + /* U+003B ";" */ + 0x0, 0x2d, 0xd3, 0x0, 0x8f, 0xfa, 0x0, 0x4f, + 0xf6, 0x0, 0x2, 0x30, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x70, + 0x0, 0x6f, 0xf8, 0x0, 0x3f, 0xfd, 0x0, 0xa, + 0xfc, 0x0, 0x9, 0xf8, 0x3, 0x8f, 0xe1, 0x5f, + 0xfa, 0x10, 0x14, 0x10, 0x0, + + /* U+003C "<" */ + 0x0, 0x0, 0x0, 0xa, 0x20, 0x0, 0x0, 0x2d, + 0xf8, 0x0, 0x0, 0x3e, 0xf6, 0x0, 0x0, 0x6f, + 0xe4, 0x0, 0x0, 0x8f, 0xd2, 0x0, 0x0, 0xbf, + 0xb0, 0x0, 0x0, 0x2e, 0xf7, 0x0, 0x0, 0x0, + 0x1c, 0xfa, 0x0, 0x0, 0x0, 0xa, 0xfc, 0x10, + 0x0, 0x0, 0x8, 0xfe, 0x30, 0x0, 0x0, 0x5, + 0xff, 0x50, 0x0, 0x0, 0x3, 0xe5, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+003D "=" */ + 0x59, 0x99, 0x99, 0x99, 0x96, 0x9f, 0xff, 0xff, + 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x59, 0x99, 0x99, 0x99, + 0x96, 0x9f, 0xff, 0xff, 0xff, 0xfa, + + /* U+003E ">" */ + 0x1a, 0x10, 0x0, 0x0, 0x6, 0xfe, 0x20, 0x0, + 0x0, 0x5, 0xff, 0x40, 0x0, 0x0, 0x3, 0xef, + 0x70, 0x0, 0x0, 0x1, 0xcf, 0xa0, 0x0, 0x0, + 0x0, 0xaf, 0xc1, 0x0, 0x0, 0x5, 0xfe, 0x30, + 0x0, 0x8, 0xfd, 0x20, 0x0, 0xb, 0xfb, 0x10, + 0x0, 0x2d, 0xf9, 0x0, 0x0, 0x3e, 0xf6, 0x0, + 0x0, 0x4, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+003F "?" */ + 0xbe, 0xc7, 0x10, 0x8, 0xdf, 0xfe, 0x40, 0x0, + 0x17, 0xff, 0x20, 0x0, 0x8, 0xfa, 0x0, 0x0, + 0x2f, 0xd0, 0x0, 0x3, 0xfc, 0x1, 0x14, 0xcf, + 0x80, 0xaf, 0xff, 0xa0, 0xa, 0xf5, 0x10, 0x0, + 0x9f, 0x10, 0x0, 0x7, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x8, 0xc2, 0x0, 0x1, 0xff, 0x90, + 0x0, 0xb, 0xe4, 0x0, 0x0, + + /* U+0040 "@" */ + 0x0, 0x0, 0x4b, 0xff, 0xb4, 0x0, 0x0, 0x9, + 0xfb, 0x56, 0xcf, 0x50, 0x0, 0x7f, 0x60, 0x0, + 0xb, 0xe0, 0x2, 0xf9, 0x0, 0x0, 0x2, 0xf6, + 0x9, 0xf1, 0x0, 0x10, 0x0, 0xea, 0xf, 0x90, + 0x2d, 0xfe, 0xf2, 0xbd, 0x4f, 0x40, 0xdd, 0x5d, + 0xf0, 0x9e, 0x8f, 0x6, 0xf5, 0xd, 0xd0, 0x9f, + 0xbd, 0xa, 0xf0, 0xf, 0xa0, 0x9e, 0xcc, 0xd, + 0xd0, 0x2f, 0x80, 0xad, 0xda, 0xf, 0xb0, 0x4f, + 0x60, 0xcb, 0xda, 0xf, 0xc0, 0x7f, 0x40, 0xf7, + 0xdb, 0xd, 0xe3, 0xef, 0x78, 0xf2, 0xbd, 0x6, + 0xff, 0x8b, 0xff, 0x70, 0x8f, 0x0, 0x23, 0x0, + 0x42, 0x0, 0x4f, 0x60, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xe2, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, + 0x85, 0x68, 0xe1, 0x0, 0x0, 0x2a, 0xef, 0xeb, + 0x60, 0x0, + + /* U+0041 "A" */ + 0x0, 0x0, 0x6f, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0xbf, 0xfe, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xcf, + 0x30, 0x0, 0x0, 0x6, 0xf7, 0x7f, 0x80, 0x0, + 0x0, 0xb, 0xf2, 0x2f, 0xd0, 0x0, 0x0, 0x1f, + 0xd0, 0xd, 0xf3, 0x0, 0x0, 0x6f, 0x80, 0x8, + 0xf8, 0x0, 0x0, 0xbf, 0x20, 0x3, 0xfd, 0x0, + 0x1, 0xfd, 0x0, 0x0, 0xdf, 0x20, 0x6, 0xfe, + 0xbb, 0xbb, 0xef, 0x80, 0xb, 0xff, 0xff, 0xff, + 0xff, 0xd0, 0x1f, 0xe0, 0x0, 0x0, 0xe, 0xf2, + 0x6f, 0x90, 0x0, 0x0, 0x9, 0xf7, 0xbf, 0x40, + 0x0, 0x0, 0x4, 0xfd, + + /* U+0042 "B" */ + 0x4f, 0xff, 0xff, 0xd8, 0x0, 0x4f, 0xd9, 0x9b, + 0xff, 0xc0, 0x4f, 0x90, 0x0, 0x1e, 0xf4, 0x4f, + 0x90, 0x0, 0xa, 0xf6, 0x4f, 0x90, 0x0, 0xc, + 0xf3, 0x4f, 0x90, 0x2, 0x9f, 0xb0, 0x4f, 0xff, + 0xff, 0xfa, 0x0, 0x4f, 0xd9, 0x9b, 0xff, 0xc1, + 0x4f, 0x90, 0x0, 0xb, 0xf9, 0x4f, 0x90, 0x0, + 0x3, 0xfd, 0x4f, 0x90, 0x0, 0x3, 0xfd, 0x4f, + 0x90, 0x0, 0xb, 0xf8, 0x4f, 0xd9, 0x9b, 0xef, + 0xc0, 0x4f, 0xff, 0xfe, 0xb6, 0x0, + + /* U+0043 "C" */ + 0x0, 0x0, 0x6c, 0xef, 0xeb, 0x40, 0x1, 0xcf, + 0xfc, 0xbd, 0xfb, 0x0, 0xbf, 0xb1, 0x0, 0x1, + 0x40, 0x4f, 0xd0, 0x0, 0x0, 0x0, 0xa, 0xf6, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0x20, 0x0, 0x0, + 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0xcf, 0x60, 0x0, 0x0, 0x0, 0x7, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x1e, 0xfa, 0x10, + 0x0, 0x13, 0x0, 0x3e, 0xff, 0xcb, 0xdf, 0xb0, + 0x0, 0x18, 0xdf, 0xfd, 0xa4, + + /* U+0044 "D" */ + 0xdf, 0xff, 0xfd, 0x92, 0x0, 0xd, 0xfa, 0x9a, + 0xdf, 0xf7, 0x0, 0xdf, 0x10, 0x0, 0x4f, 0xf4, + 0xd, 0xf1, 0x0, 0x0, 0x6f, 0xc0, 0xdf, 0x10, + 0x0, 0x0, 0xff, 0xd, 0xf1, 0x0, 0x0, 0xc, + 0xf3, 0xdf, 0x10, 0x0, 0x0, 0xbf, 0x4d, 0xf1, + 0x0, 0x0, 0xb, 0xf4, 0xdf, 0x10, 0x0, 0x0, + 0xdf, 0x2d, 0xf1, 0x0, 0x0, 0x1f, 0xe0, 0xdf, + 0x10, 0x0, 0x8, 0xf9, 0xd, 0xf1, 0x0, 0x8, + 0xfe, 0x10, 0xdf, 0xaa, 0xbf, 0xfe, 0x20, 0xd, + 0xff, 0xfe, 0xb7, 0x0, 0x0, + + /* U+0045 "E" */ + 0xdf, 0xff, 0xff, 0xff, 0x2d, 0xfa, 0x99, 0x99, + 0x91, 0xdf, 0x10, 0x0, 0x0, 0xd, 0xf1, 0x0, + 0x0, 0x0, 0xdf, 0x10, 0x0, 0x0, 0xd, 0xf1, + 0x0, 0x0, 0x0, 0xdf, 0xff, 0xff, 0xfe, 0xd, + 0xfa, 0xaa, 0xaa, 0x90, 0xdf, 0x10, 0x0, 0x0, + 0xd, 0xf1, 0x0, 0x0, 0x0, 0xdf, 0x10, 0x0, + 0x0, 0xd, 0xf1, 0x0, 0x0, 0x0, 0xdf, 0xaa, + 0xaa, 0xaa, 0x1d, 0xff, 0xff, 0xff, 0xf2, + + /* U+0046 "F" */ + 0xcf, 0xff, 0xff, 0xff, 0x2c, 0xfb, 0xaa, 0xaa, + 0xa1, 0xcf, 0x20, 0x0, 0x0, 0xc, 0xf2, 0x0, + 0x0, 0x0, 0xcf, 0x20, 0x0, 0x0, 0xc, 0xf2, + 0x0, 0x0, 0x0, 0xcf, 0xff, 0xff, 0xfd, 0xc, + 0xfa, 0x99, 0x99, 0x70, 0xcf, 0x20, 0x0, 0x0, + 0xc, 0xf2, 0x0, 0x0, 0x0, 0xcf, 0x20, 0x0, + 0x0, 0xc, 0xf2, 0x0, 0x0, 0x0, 0xcf, 0x20, + 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, 0x0, + + /* U+0047 "G" */ + 0x0, 0x0, 0x6c, 0xef, 0xeb, 0x50, 0x2, 0xdf, + 0xfd, 0xbd, 0xfd, 0x0, 0xdf, 0xa1, 0x0, 0x1, + 0x50, 0x8f, 0xb0, 0x0, 0x0, 0x0, 0xe, 0xf2, + 0x0, 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xb0, 0x0, 0xef, 0xff, 0xe4, 0xfc, + 0x0, 0x8, 0x99, 0xfe, 0x3f, 0xd0, 0x0, 0x0, + 0xf, 0xe0, 0xff, 0x10, 0x0, 0x0, 0xfe, 0xb, + 0xf8, 0x0, 0x0, 0xf, 0xe0, 0x3f, 0xf7, 0x0, + 0x0, 0xfe, 0x0, 0x5f, 0xff, 0xcb, 0xdf, 0xe0, + 0x0, 0x29, 0xdf, 0xfd, 0xa4, + + /* U+0048 "H" */ + 0xdf, 0x10, 0x0, 0x0, 0xfe, 0xdf, 0x10, 0x0, + 0x0, 0xfe, 0xdf, 0x10, 0x0, 0x0, 0xfe, 0xdf, + 0x10, 0x0, 0x0, 0xfe, 0xdf, 0x10, 0x0, 0x0, + 0xfe, 0xdf, 0x10, 0x0, 0x0, 0xfe, 0xdf, 0xff, + 0xff, 0xff, 0xfe, 0xdf, 0xba, 0xaa, 0xaa, 0xfe, + 0xdf, 0x10, 0x0, 0x0, 0xfe, 0xdf, 0x10, 0x0, + 0x0, 0xfe, 0xdf, 0x10, 0x0, 0x0, 0xfe, 0xdf, + 0x10, 0x0, 0x0, 0xfe, 0xdf, 0x10, 0x0, 0x0, + 0xfe, 0xdf, 0x10, 0x0, 0x0, 0xfe, + + /* U+0049 "I" */ + 0x2f, 0xff, 0xff, 0xff, 0xf4, 0x19, 0x99, 0xff, + 0x99, 0x92, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0x0, 0xef, 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, + 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, 0x0, + 0xef, 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, + 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, 0x0, 0xef, + 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, + 0x0, 0xef, 0x0, 0x0, 0x1a, 0xaa, 0xff, 0xaa, + 0xa2, 0x2f, 0xff, 0xff, 0xff, 0xf4, + + /* U+004A "J" */ + 0xd, 0xff, 0xff, 0xff, 0x60, 0x9a, 0xaa, 0xad, + 0xf6, 0x0, 0x0, 0x0, 0x8f, 0x60, 0x0, 0x0, + 0x8, 0xf6, 0x0, 0x0, 0x0, 0x8f, 0x60, 0x0, + 0x0, 0x8, 0xf6, 0x0, 0x0, 0x0, 0x8f, 0x60, + 0x0, 0x0, 0x8, 0xf6, 0x0, 0x0, 0x0, 0x8f, + 0x60, 0x0, 0x0, 0x8, 0xf6, 0x0, 0x0, 0x0, + 0xaf, 0x50, 0x60, 0x0, 0x2f, 0xf1, 0xf, 0xeb, + 0xbf, 0xf7, 0x0, 0x7c, 0xff, 0xc5, 0x0, + + /* U+004B "K" */ + 0x5f, 0x90, 0x0, 0xa, 0xf9, 0x5, 0xf9, 0x0, + 0x7, 0xfb, 0x0, 0x5f, 0x90, 0x4, 0xfd, 0x10, + 0x5, 0xf9, 0x1, 0xee, 0x20, 0x0, 0x5f, 0x90, + 0xcf, 0x40, 0x0, 0x5, 0xf9, 0x9f, 0x60, 0x0, + 0x0, 0x5f, 0xef, 0xa0, 0x0, 0x0, 0x5, 0xfc, + 0xff, 0x20, 0x0, 0x0, 0x5f, 0x95, 0xfd, 0x0, + 0x0, 0x5, 0xf9, 0x9, 0xfb, 0x0, 0x0, 0x5f, + 0x90, 0xc, 0xf7, 0x0, 0x5, 0xf9, 0x0, 0x2e, + 0xf4, 0x0, 0x5f, 0x90, 0x0, 0x4f, 0xe2, 0x5, + 0xf9, 0x0, 0x0, 0x8f, 0xd0, + + /* U+004C "L" */ + 0x8f, 0x70, 0x0, 0x0, 0x8, 0xf7, 0x0, 0x0, + 0x0, 0x8f, 0x70, 0x0, 0x0, 0x8, 0xf7, 0x0, + 0x0, 0x0, 0x8f, 0x70, 0x0, 0x0, 0x8, 0xf7, + 0x0, 0x0, 0x0, 0x8f, 0x70, 0x0, 0x0, 0x8, + 0xf7, 0x0, 0x0, 0x0, 0x8f, 0x70, 0x0, 0x0, + 0x8, 0xf7, 0x0, 0x0, 0x0, 0x8f, 0x70, 0x0, + 0x0, 0x8, 0xf7, 0x0, 0x0, 0x0, 0x8f, 0xca, + 0xaa, 0xaa, 0x58, 0xff, 0xff, 0xff, 0xf9, + + /* U+004D "M" */ + 0xc, 0xfa, 0x0, 0x0, 0xaf, 0xe0, 0xd, 0xff, + 0x0, 0x0, 0xff, 0xf0, 0xe, 0xdf, 0x60, 0x6, + 0xfc, 0xf0, 0xf, 0x9e, 0xb0, 0xc, 0xca, 0xf0, + 0xf, 0x99, 0xf1, 0x2f, 0x69, 0xf1, 0xf, 0x93, + 0xf7, 0x7f, 0x19, 0xf2, 0x1f, 0x80, 0xdc, 0xda, + 0x8, 0xf3, 0x2f, 0x80, 0x7f, 0xf4, 0x8, 0xf3, + 0x3f, 0x70, 0x1f, 0xe0, 0x7, 0xf4, 0x4f, 0x70, + 0x5, 0x40, 0x7, 0xf5, 0x4f, 0x60, 0x0, 0x0, + 0x6, 0xf6, 0x5f, 0x60, 0x0, 0x0, 0x6, 0xf7, + 0x6f, 0x50, 0x0, 0x0, 0x5, 0xf7, 0x7f, 0x50, + 0x0, 0x0, 0x5, 0xf8, + + /* U+004E "N" */ + 0xbf, 0xe0, 0x0, 0x0, 0xfd, 0xbf, 0xf7, 0x0, + 0x0, 0xfd, 0xbf, 0xfe, 0x0, 0x0, 0xfd, 0xbf, + 0x9f, 0x60, 0x0, 0xfd, 0xbf, 0x2f, 0xd0, 0x0, + 0xfd, 0xbf, 0x1a, 0xf5, 0x0, 0xfd, 0xbf, 0x12, + 0xfc, 0x0, 0xfd, 0xbf, 0x10, 0xbf, 0x40, 0xfd, + 0xbf, 0x10, 0x3f, 0xb0, 0xfd, 0xbf, 0x10, 0xc, + 0xf2, 0xfd, 0xbf, 0x10, 0x4, 0xf9, 0xfd, 0xbf, + 0x10, 0x0, 0xdf, 0xfd, 0xbf, 0x10, 0x0, 0x5f, + 0xfd, 0xbf, 0x10, 0x0, 0xd, 0xfd, + + /* U+004F "O" */ + 0x0, 0x4, 0xbe, 0xfd, 0x70, 0x0, 0x0, 0x7f, + 0xfb, 0xbf, 0xfc, 0x0, 0x4, 0xfe, 0x20, 0x1, + 0xcf, 0x80, 0xc, 0xf5, 0x0, 0x0, 0x2f, 0xf0, + 0x1f, 0xe0, 0x0, 0x0, 0xc, 0xf4, 0x4f, 0xb0, + 0x0, 0x0, 0x9, 0xf6, 0x5f, 0xa0, 0x0, 0x0, + 0x8, 0xf7, 0x5f, 0xa0, 0x0, 0x0, 0x8, 0xf7, + 0x4f, 0xb0, 0x0, 0x0, 0xa, 0xf6, 0x2f, 0xe0, + 0x0, 0x0, 0xd, 0xf2, 0xe, 0xf3, 0x0, 0x0, + 0x3f, 0xd0, 0x7, 0xfd, 0x10, 0x1, 0xdf, 0x60, + 0x0, 0xbf, 0xfb, 0xbf, 0xf9, 0x0, 0x0, 0x7, + 0xdf, 0xfc, 0x50, 0x0, + + /* U+0050 "P" */ + 0x4f, 0xff, 0xfe, 0xc7, 0x0, 0x4f, 0xd9, 0x9b, + 0xff, 0xc0, 0x4f, 0x90, 0x0, 0x1c, 0xf8, 0x4f, + 0x90, 0x0, 0x4, 0xfd, 0x4f, 0x90, 0x0, 0x2, + 0xfe, 0x4f, 0x90, 0x0, 0x4, 0xfb, 0x4f, 0x90, + 0x0, 0x2d, 0xf5, 0x4f, 0xda, 0xac, 0xff, 0x80, + 0x4f, 0xff, 0xfe, 0xb4, 0x0, 0x4f, 0x90, 0x0, + 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, + 0x90, 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, + 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, + + /* U+0051 "Q" */ + 0x0, 0x4, 0xbe, 0xfd, 0x70, 0x0, 0x0, 0x7, + 0xff, 0xcc, 0xff, 0xc0, 0x0, 0x3, 0xfe, 0x30, + 0x1, 0xdf, 0x80, 0x0, 0xbf, 0x50, 0x0, 0x2, + 0xff, 0x0, 0xf, 0xe0, 0x0, 0x0, 0xc, 0xf3, + 0x4, 0xfb, 0x0, 0x0, 0x0, 0xaf, 0x60, 0x5f, + 0xa0, 0x0, 0x0, 0x8, 0xf7, 0x6, 0xfa, 0x0, + 0x0, 0x0, 0x8f, 0x70, 0x5f, 0xb0, 0x0, 0x0, + 0x9, 0xf6, 0x3, 0xfd, 0x0, 0x0, 0x0, 0xcf, + 0x30, 0xf, 0xf2, 0x0, 0x0, 0x1f, 0xe0, 0x0, + 0x9f, 0xa0, 0x0, 0xa, 0xf8, 0x0, 0x1, 0xef, + 0xc6, 0x6b, 0xfd, 0x0, 0x0, 0x2, 0xcf, 0xff, + 0xfa, 0x10, 0x0, 0x0, 0x0, 0x2e, 0xe1, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0x50, 0x0, 0x20, + 0x0, 0x0, 0x3, 0xff, 0xcb, 0xec, 0x0, 0x0, + 0x0, 0x3, 0xbe, 0xec, 0x50, + + /* U+0052 "R" */ + 0x2f, 0xff, 0xff, 0xc6, 0x0, 0x2, 0xfe, 0x99, + 0xbf, 0xf9, 0x0, 0x2f, 0xb0, 0x0, 0x3f, 0xf1, + 0x2, 0xfb, 0x0, 0x0, 0xdf, 0x30, 0x2f, 0xb0, + 0x0, 0xe, 0xf1, 0x2, 0xfb, 0x0, 0x2b, 0xf9, + 0x0, 0x2f, 0xff, 0xff, 0xf8, 0x0, 0x2, 0xfe, + 0x8b, 0xfc, 0x10, 0x0, 0x2f, 0xb0, 0x7, 0xfa, + 0x0, 0x2, 0xfb, 0x0, 0xe, 0xf2, 0x0, 0x2f, + 0xb0, 0x0, 0x7f, 0xa0, 0x2, 0xfb, 0x0, 0x0, + 0xff, 0x20, 0x2f, 0xb0, 0x0, 0x8, 0xf9, 0x2, + 0xfb, 0x0, 0x0, 0x1f, 0xf1, + + /* U+0053 "S" */ + 0x0, 0x5b, 0xef, 0xfd, 0x80, 0xb, 0xff, 0xca, + 0xbd, 0xc0, 0x5f, 0xc1, 0x0, 0x0, 0x0, 0x9f, + 0x60, 0x0, 0x0, 0x0, 0x8f, 0xb0, 0x0, 0x0, + 0x0, 0x1e, 0xfc, 0x40, 0x0, 0x0, 0x2, 0xcf, + 0xfd, 0x60, 0x0, 0x0, 0x3, 0xaf, 0xfe, 0x40, + 0x0, 0x0, 0x1, 0x8f, 0xf3, 0x0, 0x0, 0x0, + 0x8, 0xf9, 0x0, 0x0, 0x0, 0x5, 0xfa, 0x20, + 0x0, 0x0, 0x1c, 0xf6, 0xdf, 0xcb, 0xbc, 0xff, + 0xb0, 0x8c, 0xef, 0xfd, 0xb6, 0x0, + + /* U+0054 "T" */ + 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xa, 0xaa, + 0xaf, 0xfa, 0xaa, 0xa1, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, + + /* U+0055 "U" */ + 0xdf, 0x10, 0x0, 0x0, 0xff, 0xdf, 0x10, 0x0, + 0x0, 0xff, 0xdf, 0x10, 0x0, 0x0, 0xff, 0xdf, + 0x10, 0x0, 0x0, 0xff, 0xdf, 0x10, 0x0, 0x0, + 0xff, 0xdf, 0x10, 0x0, 0x0, 0xff, 0xdf, 0x10, + 0x0, 0x0, 0xff, 0xdf, 0x10, 0x0, 0x0, 0xff, + 0xdf, 0x10, 0x0, 0x0, 0xff, 0xdf, 0x10, 0x0, + 0x0, 0xfe, 0xbf, 0x40, 0x0, 0x3, 0xfc, 0x7f, + 0xb0, 0x0, 0xb, 0xf6, 0xd, 0xfe, 0xaa, 0xef, + 0xb0, 0x1, 0x8d, 0xff, 0xc7, 0x0, + + /* U+0056 "V" */ + 0xcf, 0x50, 0x0, 0x0, 0x2, 0xfd, 0x7, 0xfa, + 0x0, 0x0, 0x0, 0x7f, 0x80, 0x2f, 0xf0, 0x0, + 0x0, 0xc, 0xf3, 0x0, 0xcf, 0x50, 0x0, 0x1, + 0xfd, 0x0, 0x7, 0xfa, 0x0, 0x0, 0x7f, 0x80, + 0x0, 0x2f, 0xf0, 0x0, 0xc, 0xf2, 0x0, 0x0, + 0xcf, 0x40, 0x1, 0xfd, 0x0, 0x0, 0x7, 0xf9, + 0x0, 0x6f, 0x70, 0x0, 0x0, 0x2f, 0xe0, 0xb, + 0xf2, 0x0, 0x0, 0x0, 0xcf, 0x31, 0xfc, 0x0, + 0x0, 0x0, 0x7, 0xf8, 0x5f, 0x70, 0x0, 0x0, + 0x0, 0x2f, 0xda, 0xf2, 0x0, 0x0, 0x0, 0x0, + 0xcf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x70, 0x0, 0x0, + + /* U+0057 "W" */ + 0x7f, 0x40, 0x0, 0x0, 0x2, 0xf9, 0x6f, 0x50, + 0x0, 0x0, 0x2, 0xf8, 0x5f, 0x60, 0x0, 0x0, + 0x3, 0xf7, 0x4f, 0x70, 0x0, 0x0, 0x4, 0xf5, + 0x3f, 0x80, 0x2, 0x30, 0x5, 0xf4, 0x2f, 0x90, + 0xd, 0xe0, 0x6, 0xf3, 0x1f, 0xa0, 0x3f, 0xf4, + 0x7, 0xf2, 0xf, 0xb0, 0x8e, 0xfa, 0x8, 0xf1, + 0xe, 0xc0, 0xda, 0xbf, 0x9, 0xf0, 0xd, 0xd2, + 0xf5, 0x6f, 0x59, 0xf0, 0xc, 0xe8, 0xf0, 0x1f, + 0xba, 0xe0, 0xb, 0xfc, 0xa0, 0xb, 0xfc, 0xd0, + 0xa, 0xff, 0x50, 0x5, 0xff, 0xc0, 0x9, 0xff, + 0x0, 0x0, 0xff, 0xb0, + + /* U+0058 "X" */ + 0x2f, 0xf2, 0x0, 0x0, 0x1e, 0xf2, 0x7, 0xfc, + 0x0, 0x0, 0xaf, 0x80, 0x0, 0xdf, 0x50, 0x4, + 0xfd, 0x0, 0x0, 0x3f, 0xe0, 0xd, 0xf4, 0x0, + 0x0, 0x9, 0xf9, 0x7f, 0x90, 0x0, 0x0, 0x1, + 0xef, 0xfe, 0x10, 0x0, 0x0, 0x0, 0x5f, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xfa, 0x0, 0x0, + 0x0, 0x3, 0xfd, 0xdf, 0x40, 0x0, 0x0, 0xd, + 0xf4, 0x4f, 0xe0, 0x0, 0x0, 0x8f, 0xb0, 0xb, + 0xf9, 0x0, 0x3, 0xff, 0x20, 0x2, 0xff, 0x30, + 0xd, 0xf7, 0x0, 0x0, 0x7f, 0xd0, 0x7f, 0xd0, + 0x0, 0x0, 0xd, 0xf8, + + /* U+0059 "Y" */ + 0xbf, 0x90, 0x0, 0x0, 0x5, 0xfc, 0x2, 0xff, + 0x20, 0x0, 0x0, 0xdf, 0x30, 0x9, 0xfa, 0x0, + 0x0, 0x6f, 0xa0, 0x0, 0x1e, 0xf3, 0x0, 0xe, + 0xf2, 0x0, 0x0, 0x7f, 0xc0, 0x7, 0xf8, 0x0, + 0x0, 0x0, 0xdf, 0x41, 0xfe, 0x10, 0x0, 0x0, + 0x5, 0xfc, 0x8f, 0x60, 0x0, 0x0, 0x0, 0xb, + 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xe, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, + 0x0, 0x0, 0x0, + + /* U+005A "Z" */ + 0x9f, 0xff, 0xff, 0xff, 0xfc, 0x7c, 0xcc, 0xcc, + 0xce, 0xfa, 0x0, 0x0, 0x0, 0x2f, 0xf2, 0x0, + 0x0, 0x0, 0xcf, 0x60, 0x0, 0x0, 0x6, 0xfb, + 0x0, 0x0, 0x0, 0x2f, 0xf2, 0x0, 0x0, 0x0, + 0xcf, 0x60, 0x0, 0x0, 0x6, 0xfb, 0x0, 0x0, + 0x0, 0x2f, 0xf2, 0x0, 0x0, 0x0, 0xcf, 0x60, + 0x0, 0x0, 0x6, 0xfb, 0x0, 0x0, 0x0, 0x2f, + 0xf1, 0x0, 0x0, 0x0, 0xbf, 0xec, 0xcc, 0xcc, + 0xcb, 0xdf, 0xff, 0xff, 0xff, 0xfe, + + /* U+005B "[" */ + 0x4f, 0xff, 0xff, 0x4f, 0xb8, 0x88, 0x4f, 0x70, + 0x0, 0x4f, 0x70, 0x0, 0x4f, 0x70, 0x0, 0x4f, + 0x70, 0x0, 0x4f, 0x70, 0x0, 0x4f, 0x70, 0x0, + 0x4f, 0x70, 0x0, 0x4f, 0x70, 0x0, 0x4f, 0x70, + 0x0, 0x4f, 0x70, 0x0, 0x4f, 0x70, 0x0, 0x4f, + 0x70, 0x0, 0x4f, 0x70, 0x0, 0x4f, 0x70, 0x0, + 0x4f, 0x70, 0x0, 0x4f, 0xb8, 0x88, 0x4f, 0xff, + 0xff, + + /* U+005C "\\" */ + 0x1f, 0xb0, 0x0, 0x0, 0x0, 0xa, 0xf2, 0x0, + 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0xce, 0x0, 0x0, 0x0, 0x0, 0x6f, 0x60, 0x0, + 0x0, 0x0, 0xe, 0xd0, 0x0, 0x0, 0x0, 0x8, + 0xf3, 0x0, 0x0, 0x0, 0x2, 0xfa, 0x0, 0x0, + 0x0, 0x0, 0xbf, 0x10, 0x0, 0x0, 0x0, 0x4f, + 0x80, 0x0, 0x0, 0x0, 0xd, 0xe0, 0x0, 0x0, + 0x0, 0x7, 0xf5, 0x0, 0x0, 0x0, 0x0, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0x30, 0x0, 0x0, + 0x0, 0x2f, 0x90, 0x0, 0x0, 0x0, 0xc, 0xf1, + 0x0, 0x0, 0x0, 0x5, 0xf7, 0x0, 0x0, 0x0, + 0x0, 0x76, + + /* U+005D "]" */ + 0xef, 0xff, 0xf6, 0x78, 0x8b, 0xf6, 0x0, 0x6, + 0xf6, 0x0, 0x6, 0xf6, 0x0, 0x6, 0xf6, 0x0, + 0x6, 0xf6, 0x0, 0x6, 0xf6, 0x0, 0x6, 0xf6, + 0x0, 0x6, 0xf6, 0x0, 0x6, 0xf6, 0x0, 0x6, + 0xf6, 0x0, 0x6, 0xf6, 0x0, 0x6, 0xf6, 0x0, + 0x6, 0xf6, 0x0, 0x6, 0xf6, 0x0, 0x6, 0xf6, + 0x0, 0x6, 0xf6, 0x78, 0x8b, 0xf6, 0xef, 0xff, + 0xf6, + + /* U+005E "^" */ + 0x0, 0x1, 0xff, 0x10, 0x0, 0x0, 0x9, 0xef, + 0xa0, 0x0, 0x0, 0x2f, 0x68, 0xf3, 0x0, 0x0, + 0xbd, 0x0, 0xec, 0x0, 0x4, 0xf5, 0x0, 0x6f, + 0x60, 0xd, 0xc0, 0x0, 0xc, 0xe1, 0x6f, 0x40, + 0x0, 0x4, 0xf9, + + /* U+005F "_" */ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf1, + + /* U+0060 "`" */ + 0x3, 0x23, 0xfd, 0x2f, 0xc1, 0xfb, 0xf, 0xa0, + 0xf9, + + /* U+0061 "a" */ + 0x4, 0xad, 0xff, 0xd7, 0x0, 0xa, 0xfc, 0xaa, + 0xef, 0xb0, 0x3, 0x10, 0x0, 0x1e, 0xf2, 0x0, + 0x0, 0x0, 0x9, 0xf5, 0x0, 0x0, 0x11, 0x19, + 0xf5, 0x2, 0xaf, 0xff, 0xff, 0xf5, 0x2f, 0xf9, + 0x54, 0x4b, 0xf5, 0x7f, 0x80, 0x0, 0x9, 0xf5, + 0x8f, 0x80, 0x0, 0x5e, 0xf5, 0x3f, 0xfa, 0x9d, + 0xfc, 0xf5, 0x4, 0xcf, 0xfb, 0x35, 0xf5, + + /* U+0062 "b" */ + 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, + 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, + 0x90, 0x0, 0x0, 0x0, 0x4f, 0x91, 0xae, 0xfb, + 0x20, 0x4f, 0xae, 0xfb, 0xcf, 0xe1, 0x4f, 0xfc, + 0x10, 0xb, 0xf7, 0x4f, 0xd1, 0x0, 0x3, 0xfb, + 0x4f, 0x90, 0x0, 0x0, 0xfd, 0x4f, 0x90, 0x0, + 0x0, 0xfe, 0x4f, 0x90, 0x0, 0x0, 0xfd, 0x4f, + 0x90, 0x0, 0x4, 0xf9, 0x4f, 0x90, 0x0, 0x1d, + 0xf3, 0x4f, 0xfb, 0x8a, 0xef, 0x70, 0x17, 0xce, + 0xfe, 0xb4, 0x0, + + /* U+0063 "c" */ + 0x0, 0x5, 0xcf, 0xfe, 0xa0, 0x0, 0xaf, 0xfa, + 0xac, 0xf1, 0x7, 0xfd, 0x20, 0x0, 0x10, 0xe, + 0xf3, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, + 0x0, 0x4f, 0xa0, 0x0, 0x0, 0x0, 0x3f, 0xc0, + 0x0, 0x0, 0x0, 0x1f, 0xf1, 0x0, 0x0, 0x0, + 0xa, 0xfb, 0x10, 0x0, 0x10, 0x1, 0xef, 0xeb, + 0xac, 0xf1, 0x0, 0x18, 0xdf, 0xfd, 0x90, + + /* U+0064 "d" */ + 0x0, 0x0, 0x0, 0x9, 0xf5, 0x0, 0x0, 0x0, + 0x9, 0xf5, 0x0, 0x0, 0x0, 0x9, 0xf5, 0x0, + 0x0, 0x0, 0x9, 0xf5, 0x0, 0x3a, 0xef, 0xee, + 0xf5, 0x5, 0xff, 0xb9, 0xbf, 0xf5, 0x1f, 0xe2, + 0x0, 0x9, 0xf5, 0x8f, 0x60, 0x0, 0x9, 0xf5, + 0xbf, 0x20, 0x0, 0x9, 0xf5, 0xcf, 0x10, 0x0, + 0x9, 0xf5, 0xbf, 0x10, 0x0, 0x9, 0xf5, 0xaf, + 0x40, 0x0, 0xd, 0xf5, 0x6f, 0xa0, 0x0, 0xbf, + 0xf5, 0xd, 0xfa, 0x7d, 0xe9, 0xf5, 0x1, 0xbf, + 0xea, 0x16, 0xf5, + + /* U+0065 "e" */ + 0x0, 0x3b, 0xef, 0xd6, 0x0, 0x4, 0xff, 0xa9, + 0xdf, 0xa0, 0x1e, 0xf2, 0x0, 0xc, 0xf4, 0x6f, + 0x80, 0x0, 0x4, 0xfa, 0xaf, 0x62, 0x22, 0x24, + 0xfc, 0xbf, 0xff, 0xff, 0xff, 0xfd, 0xaf, 0x85, + 0x55, 0x55, 0x53, 0x8f, 0x70, 0x0, 0x0, 0x0, + 0x2f, 0xe2, 0x0, 0x0, 0x0, 0x7, 0xff, 0xb9, + 0x9a, 0xd3, 0x0, 0x4b, 0xef, 0xfd, 0xa2, + + /* U+0066 "f" */ + 0x0, 0x0, 0x1, 0x9d, 0xff, 0xd3, 0x0, 0x0, + 0xd, 0xfd, 0x99, 0xb4, 0x0, 0x0, 0x6f, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0x50, 0x0, 0x0, + 0x0, 0x0, 0xaf, 0x30, 0x0, 0x0, 0x0, 0x0, + 0xaf, 0x30, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x19, 0x99, 0xdf, 0xa9, 0x99, 0x80, + 0x0, 0x0, 0xaf, 0x30, 0x0, 0x0, 0x0, 0x0, + 0xaf, 0x30, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x30, + 0x0, 0x0, 0x0, 0x0, 0xaf, 0x30, 0x0, 0x0, + 0x0, 0x0, 0xaf, 0x30, 0x0, 0x0, 0x0, 0x0, + 0xaf, 0x30, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x30, + 0x0, 0x0, + + /* U+0067 "g" */ + 0x0, 0x5c, 0xff, 0xff, 0xff, 0x30, 0x8f, 0xd7, + 0x8e, 0xfe, 0xb2, 0x2f, 0xe0, 0x0, 0x2f, 0xd0, + 0x4, 0xf9, 0x0, 0x0, 0xdf, 0x10, 0x3f, 0xc0, + 0x0, 0xe, 0xf0, 0x0, 0xcf, 0x92, 0x3b, 0xf8, + 0x0, 0xd, 0xff, 0xff, 0xf8, 0x0, 0x6, 0xf6, + 0x14, 0x31, 0x0, 0x0, 0x8f, 0x50, 0x0, 0x0, + 0x0, 0x5, 0xff, 0xaa, 0xa9, 0x83, 0x0, 0xd, + 0xff, 0xff, 0xff, 0xf9, 0xa, 0xf7, 0x0, 0x0, + 0x4f, 0xf1, 0xff, 0x10, 0x0, 0x1, 0xff, 0x1b, + 0xfe, 0x98, 0x8a, 0xef, 0x70, 0x7, 0xce, 0xff, + 0xea, 0x40, 0x0, + + /* U+0068 "h" */ + 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, + 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, + 0x90, 0x0, 0x0, 0x0, 0x4f, 0x91, 0xae, 0xea, + 0x10, 0x4f, 0xbe, 0xea, 0xdf, 0xc0, 0x4f, 0xfc, + 0x10, 0xd, 0xf3, 0x4f, 0xd1, 0x0, 0x8, 0xf5, + 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, + 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, + 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, + 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, + 0x0, 0x7, 0xf6, + + /* U+0069 "i" */ + 0x0, 0x1, 0xde, 0x20, 0x0, 0x0, 0x5, 0xff, + 0x70, 0x0, 0x0, 0x1, 0xcd, 0x20, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0xff, 0x40, + 0x0, 0x6, 0x88, 0xdf, 0x40, 0x0, 0x0, 0x0, + 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, + 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, + 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, + 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, + 0x0, 0x19, 0x99, 0xdf, 0xa9, 0x94, 0x2f, 0xff, + 0xff, 0xff, 0xf8, + + /* U+006A "j" */ + 0x0, 0x0, 0x3, 0xec, 0x10, 0x0, 0x0, 0x8f, + 0xf5, 0x0, 0x0, 0x2, 0xdc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0x1, 0x88, + 0x88, 0x8e, 0xf0, 0x0, 0x0, 0x0, 0xdf, 0x0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0xdf, + 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, + 0xdf, 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, + 0x0, 0xdf, 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, + 0x0, 0x0, 0xef, 0x0, 0x0, 0x0, 0xf, 0xe0, + 0x10, 0x0, 0x8, 0xf9, 0x9, 0xea, 0x9c, 0xfe, + 0x10, 0x5c, 0xef, 0xe9, 0x10, 0x0, + + /* U+006B "k" */ + 0xf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xd0, 0x0, 0x0, 0x0, + 0x0, 0xfd, 0x0, 0x0, 0x0, 0x0, 0xf, 0xd0, + 0x0, 0xc, 0xfa, 0x0, 0xfd, 0x0, 0xb, 0xfa, + 0x0, 0xf, 0xd0, 0xb, 0xfa, 0x0, 0x0, 0xfd, + 0xa, 0xfa, 0x0, 0x0, 0xf, 0xda, 0xfa, 0x0, + 0x0, 0x0, 0xfd, 0xcf, 0x70, 0x0, 0x0, 0xf, + 0xd1, 0xef, 0x50, 0x0, 0x0, 0xfd, 0x2, 0xff, + 0x40, 0x0, 0xf, 0xd0, 0x4, 0xff, 0x30, 0x0, + 0xfd, 0x0, 0x6, 0xfe, 0x20, 0xf, 0xd0, 0x0, + 0x9, 0xfd, 0x10, + + /* U+006C "l" */ + 0xc, 0xff, 0xff, 0x40, 0x0, 0x6, 0x88, 0xdf, + 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, + 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, + 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, + 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, + 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, + 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0x0, + 0x0, 0x9f, 0x40, 0x0, 0x0, 0x0, 0x9f, 0x40, + 0x0, 0x19, 0x99, 0xdf, 0xa9, 0x94, 0x2f, 0xff, + 0xff, 0xff, 0xf8, + + /* U+006D "m" */ + 0xf, 0x66, 0xed, 0x24, 0xde, 0x50, 0xf, 0xae, + 0x7f, 0xae, 0x8e, 0xe0, 0xf, 0xf6, 0xd, 0xf9, + 0xa, 0xf1, 0xf, 0xd0, 0xd, 0xf1, 0x9, 0xf1, + 0xf, 0xb0, 0xd, 0xe0, 0x9, 0xf2, 0xf, 0xb0, + 0xd, 0xe0, 0x9, 0xf2, 0xf, 0xb0, 0xd, 0xe0, + 0x9, 0xf2, 0xf, 0xb0, 0xd, 0xe0, 0x9, 0xf2, + 0xf, 0xb0, 0xd, 0xe0, 0x9, 0xf2, 0xf, 0xb0, + 0xd, 0xe0, 0x9, 0xf2, 0xf, 0xb0, 0xd, 0xe0, + 0x9, 0xf2, + + /* U+006E "n" */ + 0x4f, 0x62, 0xbf, 0xea, 0x10, 0x4f, 0xbf, 0xc7, + 0xaf, 0xc0, 0x4f, 0xfa, 0x0, 0xc, 0xf3, 0x4f, + 0xc0, 0x0, 0x8, 0xf5, 0x4f, 0x90, 0x0, 0x7, + 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, + 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, + 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, + 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, + + /* U+006F "o" */ + 0x0, 0x5, 0xbf, 0xfd, 0x70, 0x0, 0x0, 0x8f, + 0xfa, 0xae, 0xfc, 0x0, 0x4, 0xfd, 0x10, 0x1, + 0xcf, 0x70, 0xb, 0xf4, 0x0, 0x0, 0x3f, 0xd0, + 0xe, 0xf0, 0x0, 0x0, 0xe, 0xf0, 0xf, 0xe0, + 0x0, 0x0, 0xd, 0xf1, 0xf, 0xf0, 0x0, 0x0, + 0xe, 0xf0, 0xc, 0xf4, 0x0, 0x0, 0x3f, 0xc0, + 0x6, 0xfc, 0x10, 0x1, 0xcf, 0x50, 0x0, 0xbf, + 0xea, 0xae, 0xfa, 0x0, 0x0, 0x7, 0xdf, 0xfc, + 0x60, 0x0, + + /* U+0070 "p" */ + 0x4f, 0x62, 0xae, 0xfb, 0x20, 0x4f, 0xbf, 0xd7, + 0x9f, 0xe1, 0x4f, 0xfa, 0x0, 0x9, 0xf7, 0x4f, + 0xc0, 0x0, 0x2, 0xfb, 0x4f, 0x90, 0x0, 0x0, + 0xfd, 0x4f, 0x90, 0x0, 0x0, 0xfe, 0x4f, 0x90, + 0x0, 0x1, 0xfd, 0x4f, 0x90, 0x0, 0x5, 0xf9, + 0x4f, 0x90, 0x0, 0x1d, 0xf3, 0x4f, 0xfb, 0x89, + 0xef, 0x70, 0x4f, 0xee, 0xfe, 0xb4, 0x0, 0x4f, + 0x90, 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, + 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4f, 0x90, + 0x0, 0x0, 0x0, + + /* U+0071 "q" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xef, + 0xeb, 0xd5, 0x5, 0xfe, 0x98, 0xaf, 0xf5, 0x1f, + 0xe1, 0x0, 0x9, 0xf5, 0x8f, 0x70, 0x0, 0x9, + 0xf5, 0xbf, 0x30, 0x0, 0x9, 0xf5, 0xcf, 0x10, + 0x0, 0x9, 0xf5, 0xbf, 0x20, 0x0, 0x9, 0xf5, + 0xaf, 0x50, 0x0, 0x1e, 0xf5, 0x6f, 0xc0, 0x1, + 0xdf, 0xf5, 0xd, 0xfc, 0xaf, 0xe9, 0xf5, 0x1, + 0xbf, 0xe9, 0x18, 0xf5, 0x0, 0x0, 0x0, 0x9, + 0xf5, 0x0, 0x0, 0x0, 0x9, 0xf5, 0x0, 0x0, + 0x0, 0x9, 0xf5, 0x0, 0x0, 0x0, 0x9, 0xf5, + + /* U+0072 "r" */ + 0xde, 0x5, 0xcf, 0xe8, 0x0, 0xde, 0x8f, 0xa7, + 0xdf, 0x70, 0xdf, 0xf5, 0x0, 0x2f, 0xd0, 0xdf, + 0x60, 0x0, 0xe, 0xf0, 0xdf, 0x0, 0x0, 0x2, + 0x20, 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0x0, 0x0, 0x0, 0x0, + + /* U+0073 "s" */ + 0x0, 0x4b, 0xef, 0xfd, 0x60, 0x5, 0xff, 0xa9, + 0xac, 0x80, 0xc, 0xf2, 0x0, 0x0, 0x0, 0xc, + 0xf3, 0x0, 0x0, 0x0, 0x6, 0xff, 0xa4, 0x0, + 0x0, 0x0, 0x4d, 0xff, 0xf8, 0x0, 0x0, 0x0, + 0x27, 0xef, 0xc0, 0x0, 0x0, 0x0, 0xd, 0xf2, + 0x0, 0x0, 0x0, 0xd, 0xf2, 0xf, 0xca, 0x9a, + 0xef, 0xa0, 0xb, 0xdf, 0xff, 0xc6, 0x0, + + /* U+0074 "t" */ + 0x0, 0x0, 0x23, 0x0, 0x0, 0x0, 0x0, 0x4f, + 0x90, 0x0, 0x0, 0x0, 0x4, 0xf9, 0x0, 0x0, + 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x5f, 0xff, + 0xff, 0xff, 0xff, 0x62, 0x99, 0xbf, 0xc9, 0x99, + 0x93, 0x0, 0x4, 0xf9, 0x0, 0x0, 0x0, 0x0, + 0x4f, 0x90, 0x0, 0x0, 0x0, 0x4, 0xf9, 0x0, + 0x0, 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, + 0x4, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x4f, 0x90, + 0x0, 0x0, 0x0, 0x1, 0xfe, 0x10, 0x0, 0x0, + 0x0, 0xa, 0xfe, 0xaa, 0xb5, 0x0, 0x0, 0x9, + 0xef, 0xfd, 0x40, + + /* U+0075 "u" */ + 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, + 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, + 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, 0x0, 0x7, + 0xf6, 0x4f, 0x90, 0x0, 0x7, 0xf6, 0x4f, 0x90, + 0x0, 0x7, 0xf6, 0x3f, 0xa0, 0x0, 0xa, 0xf6, + 0x1f, 0xd0, 0x0, 0x8f, 0xf6, 0xb, 0xfb, 0x7b, + 0xfb, 0xf6, 0x1, 0xae, 0xfc, 0x44, 0xf6, + + /* U+0076 "v" */ + 0x1f, 0xf0, 0x0, 0x0, 0xe, 0xf2, 0xb, 0xf6, + 0x0, 0x0, 0x4f, 0xb0, 0x5, 0xfb, 0x0, 0x0, + 0xaf, 0x50, 0x0, 0xef, 0x10, 0x0, 0xfe, 0x0, + 0x0, 0x9f, 0x70, 0x5, 0xf9, 0x0, 0x0, 0x2f, + 0xd0, 0xb, 0xf3, 0x0, 0x0, 0xc, 0xf3, 0x1f, + 0xc0, 0x0, 0x0, 0x6, 0xf8, 0x7f, 0x60, 0x0, + 0x0, 0x0, 0xfd, 0xcf, 0x10, 0x0, 0x0, 0x0, + 0xaf, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf4, + 0x0, 0x0, + + /* U+0077 "w" */ + 0x8f, 0x40, 0x0, 0x0, 0x3, 0xfa, 0x6f, 0x60, + 0x0, 0x0, 0x4, 0xf7, 0x4f, 0x80, 0x2, 0x30, + 0x6, 0xf5, 0x1f, 0xa0, 0xe, 0xe0, 0x8, 0xf3, + 0xf, 0xc0, 0x3f, 0xf4, 0xa, 0xf1, 0xd, 0xe0, + 0x8e, 0xea, 0xb, 0xe0, 0xb, 0xf0, 0xda, 0xaf, + 0xd, 0xc0, 0x8, 0xf4, 0xf4, 0x5f, 0x5f, 0xa0, + 0x6, 0xfb, 0xf0, 0xf, 0xbf, 0x70, 0x4, 0xff, + 0xa0, 0xa, 0xff, 0x50, 0x1, 0xff, 0x50, 0x4, + 0xff, 0x30, + + /* U+0078 "x" */ + 0xa, 0xfa, 0x0, 0x0, 0x6f, 0xd0, 0x1, 0xef, + 0x50, 0x1, 0xef, 0x30, 0x0, 0x3f, 0xe1, 0xb, + 0xf6, 0x0, 0x0, 0x8, 0xfa, 0x5f, 0xb0, 0x0, + 0x0, 0x0, 0xcf, 0xfe, 0x10, 0x0, 0x0, 0x0, + 0x4f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xfe, + 0x10, 0x0, 0x0, 0x9, 0xf9, 0x7f, 0xb0, 0x0, + 0x0, 0x5f, 0xd0, 0xc, 0xf8, 0x0, 0x2, 0xff, + 0x30, 0x2, 0xff, 0x40, 0xd, 0xf8, 0x0, 0x0, + 0x6f, 0xe1, + + /* U+0079 "y" */ + 0x1f, 0xf1, 0x0, 0x0, 0xe, 0xf1, 0xb, 0xf6, + 0x0, 0x0, 0x4f, 0xb0, 0x4, 0xfc, 0x0, 0x0, + 0xaf, 0x50, 0x0, 0xdf, 0x30, 0x0, 0xfe, 0x0, + 0x0, 0x7f, 0x90, 0x5, 0xf9, 0x0, 0x0, 0x1f, + 0xf0, 0xb, 0xf2, 0x0, 0x0, 0xa, 0xf5, 0x1f, + 0xc0, 0x0, 0x0, 0x3, 0xfb, 0x7f, 0x60, 0x0, + 0x0, 0x0, 0xdf, 0xdf, 0x0, 0x0, 0x0, 0x0, + 0x6f, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x8f, 0xb0, 0x0, 0x0, + 0x0, 0x5, 0xff, 0x20, 0x0, 0x0, 0x4a, 0xcf, + 0xf5, 0x0, 0x0, 0x0, 0x5f, 0xea, 0x30, 0x0, + 0x0, 0x0, + + /* U+007A "z" */ + 0x1f, 0xff, 0xff, 0xff, 0xf1, 0x9, 0x99, 0x99, + 0xbf, 0xe0, 0x0, 0x0, 0x0, 0xdf, 0x40, 0x0, + 0x0, 0x9, 0xf8, 0x0, 0x0, 0x0, 0x5f, 0xc0, + 0x0, 0x0, 0x2, 0xfe, 0x10, 0x0, 0x0, 0xd, + 0xf4, 0x0, 0x0, 0x0, 0x9f, 0x80, 0x0, 0x0, + 0x5, 0xfc, 0x0, 0x0, 0x0, 0x1f, 0xfb, 0x99, + 0x99, 0x94, 0x3f, 0xff, 0xff, 0xff, 0xf7, + + /* U+007B "{" */ + 0x0, 0x0, 0x19, 0xef, 0xa0, 0x0, 0xc, 0xfd, + 0x95, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, + 0x80, 0x0, 0x0, 0x4, 0xf8, 0x0, 0x0, 0x0, + 0x4f, 0x80, 0x0, 0x0, 0x7, 0xf6, 0x0, 0x2, + 0x8a, 0xfc, 0x0, 0x0, 0x4f, 0xfd, 0x40, 0x0, + 0x0, 0x3, 0xdf, 0x20, 0x0, 0x0, 0x5, 0xf7, + 0x0, 0x0, 0x0, 0x4f, 0x80, 0x0, 0x0, 0x4, + 0xf8, 0x0, 0x0, 0x0, 0x4f, 0x80, 0x0, 0x0, + 0x4, 0xf8, 0x0, 0x0, 0x0, 0x3f, 0x90, 0x0, + 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x9, 0xfd, + 0x95, 0x0, 0x0, 0x8, 0xdf, 0xa0, + + /* U+007C "|" */ + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, + + /* U+007D "}" */ + 0x8f, 0xe9, 0x10, 0x0, 0x4, 0x8c, 0xfd, 0x0, + 0x0, 0x0, 0xb, 0xf3, 0x0, 0x0, 0x0, 0x7f, + 0x50, 0x0, 0x0, 0x7, 0xf5, 0x0, 0x0, 0x0, + 0x6f, 0x50, 0x0, 0x0, 0x5, 0xf9, 0x0, 0x0, + 0x0, 0xb, 0xfb, 0x82, 0x0, 0x0, 0x2c, 0xff, + 0x50, 0x0, 0xe, 0xd3, 0x0, 0x0, 0x5, 0xf6, + 0x0, 0x0, 0x0, 0x6f, 0x50, 0x0, 0x0, 0x6, + 0xf5, 0x0, 0x0, 0x0, 0x6f, 0x50, 0x0, 0x0, + 0x6, 0xf5, 0x0, 0x0, 0x0, 0x7f, 0x40, 0x0, + 0x0, 0xc, 0xf2, 0x0, 0x4, 0x8d, 0xfb, 0x0, + 0x0, 0x8f, 0xd8, 0x0, 0x0, 0x0, + + /* U+007E "~" */ + 0x0, 0x6a, 0x81, 0x0, 0x0, 0x10, 0x8, 0xff, + 0xfe, 0x20, 0x5, 0xf5, 0xf, 0xd1, 0x5f, 0xe2, + 0x9, 0xf3, 0x3f, 0x70, 0x5, 0xff, 0xcf, 0xc0, + 0x16, 0x20, 0x0, 0x4c, 0xfb, 0x10, + + /* U+007F "" */ + + /* U+4E2D "中" */ + 0x0, 0x0, 0x0, 0x0, 0x4, 0x50, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0xa, 0xaa, 0xaa, 0xaa, 0xae, 0xfa, + 0xaa, 0xaa, 0xaa, 0xa6, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x1f, 0xa0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x2, 0xf9, + 0x1f, 0xa0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, + 0x2, 0xf9, 0x1f, 0xa0, 0x0, 0x0, 0xd, 0xf0, + 0x0, 0x0, 0x2, 0xf9, 0x1f, 0xa0, 0x0, 0x0, + 0xd, 0xf0, 0x0, 0x0, 0x2, 0xf9, 0x1f, 0xa0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x2, 0xf9, + 0x1f, 0xd9, 0x99, 0x99, 0x9e, 0xf9, 0x99, 0x99, + 0x9a, 0xf9, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf9, 0x1f, 0xa0, 0x0, 0x0, + 0xd, 0xf0, 0x0, 0x0, 0x2, 0xf9, 0x2, 0x10, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0x21, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xf0, + 0x0, 0x0, 0x0, 0x0, + + /* U+6587 "æ–‡" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, + 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x4, 0xfd, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x59, 0x99, 0x99, 0x99, + 0x99, 0xbc, 0x99, 0x99, 0x99, 0x99, 0x90, 0x8f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf1, 0x0, 0x0, 0x6f, 0x50, 0x0, 0x0, + 0x0, 0xd, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0x90, 0x0, 0x0, 0x0, 0x1f, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xd0, 0x0, 0x0, 0x0, 0x5f, + 0x70, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf4, 0x0, + 0x0, 0x0, 0xbf, 0x20, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xfb, 0x0, 0x0, 0x2, 0xfb, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0x40, 0x0, 0xa, + 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, + 0xd0, 0x0, 0x4f, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x6, 0xfb, 0x2, 0xef, 0x20, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xad, + 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xc, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0xe4, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6e, 0xfe, + 0x59, 0xff, 0xc5, 0x0, 0x0, 0x0, 0x0, 0x2, + 0x8e, 0xff, 0x91, 0x0, 0x4c, 0xff, 0xe8, 0x30, + 0x0, 0x16, 0xcf, 0xff, 0x92, 0x0, 0x0, 0x0, + 0x5c, 0xff, 0xfe, 0x90, 0x5f, 0xfe, 0x81, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3a, 0xff, 0x80, 0x6, + 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x5, 0x0 +}; + + +/*--------------------- + * GLYPH DESCRIPTION + *--------------------*/ + +static const sgl_font_table_t consolas24_tab[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 194, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 194, .box_w = 4, .box_h = 15, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 30, .adv_w = 194, .box_w = 8, .box_h = 6, .ofs_x = 2, .ofs_y = 9}, + {.bitmap_index = 54, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 138, .adv_w = 194, .box_w = 10, .box_h = 19, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 233, .adv_w = 194, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 323, .adv_w = 194, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 421, .adv_w = 194, .box_w = 4, .box_h = 6, .ofs_x = 4, .ofs_y = 9}, + {.bitmap_index = 433, .adv_w = 194, .box_w = 7, .box_h = 22, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 510, .adv_w = 194, .box_w = 7, .box_h = 22, .ofs_x = 2, .ofs_y = -5}, + {.bitmap_index = 587, .adv_w = 194, .box_w = 10, .box_h = 10, .ofs_x = 1, .ofs_y = 5}, + {.bitmap_index = 637, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 703, .adv_w = 194, .box_w = 6, .box_h = 8, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 727, .adv_w = 194, .box_w = 8, .box_h = 2, .ofs_x = 2, .ofs_y = 5}, + {.bitmap_index = 735, .adv_w = 194, .box_w = 4, .box_h = 4, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 743, .adv_w = 194, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 833, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 917, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 987, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1057, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1127, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1211, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1281, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1351, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1421, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1491, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1561, .adv_w = 194, .box_w = 4, .box_h = 11, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 1583, .adv_w = 194, .box_w = 6, .box_h = 15, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 1628, .adv_w = 194, .box_w = 9, .box_h = 13, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 1687, .adv_w = 194, .box_w = 10, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 1717, .adv_w = 194, .box_w = 9, .box_h = 13, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 1776, .adv_w = 194, .box_w = 7, .box_h = 15, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 1829, .adv_w = 194, .box_w = 12, .box_h = 19, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 1943, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2027, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2097, .adv_w = 194, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2174, .adv_w = 194, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2251, .adv_w = 194, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2314, .adv_w = 194, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2377, .adv_w = 194, .box_w = 11, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2454, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2524, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2594, .adv_w = 194, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2657, .adv_w = 194, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2734, .adv_w = 194, .box_w = 9, .box_h = 14, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2797, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2881, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2951, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3035, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3105, .adv_w = 194, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 3222, .adv_w = 194, .box_w = 11, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3299, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3369, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3453, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3523, .adv_w = 194, .box_w = 13, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3614, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3698, .adv_w = 194, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3782, .adv_w = 194, .box_w = 13, .box_h = 14, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3873, .adv_w = 194, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3943, .adv_w = 194, .box_w = 6, .box_h = 19, .ofs_x = 3, .ofs_y = -4}, + {.bitmap_index = 4000, .adv_w = 194, .box_w = 10, .box_h = 18, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 4090, .adv_w = 194, .box_w = 6, .box_h = 19, .ofs_x = 3, .ofs_y = -4}, + {.bitmap_index = 4147, .adv_w = 194, .box_w = 10, .box_h = 7, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 4182, .adv_w = 194, .box_w = 13, .box_h = 2, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4195, .adv_w = 90, .box_w = 3, .box_h = 6, .ofs_x = 1, .ofs_y = 12}, + {.bitmap_index = 4204, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4259, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4334, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4389, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4464, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4519, .adv_w = 194, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4609, .adv_w = 194, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 4692, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4767, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4842, .adv_w = 194, .box_w = 9, .box_h = 19, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 4928, .adv_w = 194, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5011, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5086, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5152, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5207, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5273, .adv_w = 194, .box_w = 10, .box_h = 15, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 5348, .adv_w = 194, .box_w = 10, .box_h = 16, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 5428, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5483, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5538, .adv_w = 194, .box_w = 11, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5621, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5676, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5742, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5808, .adv_w = 194, .box_w = 12, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5874, .adv_w = 194, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 5964, .adv_w = 194, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 6019, .adv_w = 194, .box_w = 9, .box_h = 19, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 6105, .adv_w = 194, .box_w = 2, .box_h = 22, .ofs_x = 5, .ofs_y = -4}, + {.bitmap_index = 6127, .adv_w = 194, .box_w = 9, .box_h = 19, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 6213, .adv_w = 194, .box_w = 12, .box_h = 5, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 6243, .adv_w = 194, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6243, .adv_w = 352, .box_w = 20, .box_h = 22, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 6463, .adv_w = 352, .box_w = 22, .box_h = 22, .ofs_x = 0, .ofs_y = -3} +}; + +static const uint32_t unicode_list_1[] = { + 0x0, 0x175a +}; + +static const sgl_font_unicode_t consolas24_unicode[] = { + { .offset = 32, .len = 96, .list = NULL, .tab_offset = 1, }, + { .offset = 20013, .len = 2, .list = unicode_list_1, .tab_offset = 97, }, +}; + + +const sgl_font_t consolas24 = { + .bitmap = glyph_bitmap, + .table = consolas24_tab, + .font_table_size = SGL_ARRAY_SIZE(consolas24_tab), + .font_height = 24, + .base_line = 5, + .bpp = 4, + .unicode = consolas24_unicode, + .unicode_num = 2, +}; + +#endif /* !CONFIG_SGL_FONT_CONSOLAS24*/ diff --git a/User/system/sgl/fonts/sgl_ascii_consolas24_compress.c b/User/system/sgl/fonts/sgl_ascii_consolas24_compress.c new file mode 100644 index 0000000..f244a12 --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_consolas24_compress.c @@ -0,0 +1,1183 @@ +/* source/fonts/sgl_ascii_consolas24_compress.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +#if (CONFIG_SGL_FONT_CONSOLAS24_COMPRESS) + +static const uint8_t font_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0xaf, 0xc0, 0xaf, 0xc0, 0x9f, 0xb0, 0x9f, 0xb0, + 0x8f, 0xa0, 0x8f, 0xa0, 0x7f, 0xa0, 0x7f, 0x90, + 0x6f, 0x90, 0x6f, 0x80, 0x5f, 0x80, 0x28, 0x40, + 0x0f, 0xe9, 0xfb, 0x0e, 0xff, 0x03, 0xfc, 0x80, + + /* U+0022 "\"" */ + 0xff, 0x48, 0x37, 0xf8, 0xbb, 0xe0, 0x17, 0xfc, + 0x3b, 0xee, 0x09, 0xfe, 0x0c, 0xf6, 0x03, 0xff, + 0x05, 0xfa, 0x81, 0x7f, 0x02, 0xc1, 0x00, 0x21, + 0x80, + + /* U+0023 "#" */ + 0x00, 0xdf, 0x80, 0x03, 0xf8, 0x00, 0xe1, 0xfa, + 0x00, 0x2f, 0xa8, 0x07, 0x1f, 0xc0, 0x01, 0xfc, + 0xc0, 0x2e, 0xff, 0xff, 0x58, 0x3c, 0x5f, 0xd4, + 0x43, 0x7e, 0x20, 0xa0, 0x14, 0x79, 0x80, 0x33, + 0x80, 0x3d, 0x3e, 0x20, 0x0e, 0xd0, 0x0f, 0x5f, + 0x80, 0x5f, 0x60, 0x1e, 0xce, 0x00, 0x0f, 0xd0, + 0x05, 0x1f, 0xff, 0xf0, 0xa4, 0x43, 0xf6, 0x21, + 0x5f, 0x71, 0x00, 0x08, 0x7e, 0x80, 0x0d, 0xea, + 0x01, 0xc7, 0xf0, 0x00, 0x7f, 0x40, 0x0e, 0x4f, + 0x70, 0x04, 0xf9, 0x00, 0x73, 0x7a, 0x80, 0x2b, + 0xc4, 0x02, + + /* U+0024 "$" */ + 0x00, 0xf4, 0x20, 0x07, 0xe2, 0xf8, 0x00, 0xfc, + 0x9e, 0xc0, 0x1c, 0x75, 0xdf, 0xf6, 0xb8, 0x02, + 0x3f, 0xd7, 0xbf, 0x9d, 0x60, 0x7f, 0xc4, 0x17, + 0xe0, 0x1a, 0x3e, 0x80, 0x1b, 0xa0, 0x0d, 0x1f, + 0xa0, 0x0f, 0xb0, 0x0c, 0x5f, 0xec, 0x5f, 0x90, + 0x0e, 0x4e, 0xff, 0xa8, 0x03, 0xe7, 0xef, 0xf9, + 0xc0, 0x3d, 0x1f, 0x7f, 0xeb, 0x00, 0xea, 0xf0, + 0x3e, 0xf7, 0x00, 0xd9, 0xc0, 0x08, 0xfb, 0x00, + 0xdf, 0x80, 0x09, 0xfa, 0x54, 0x11, 0x7d, 0x02, + 0xff, 0x96, 0xff, 0xff, 0x50, 0x35, 0xf7, 0xfd, + 0xd6, 0x80, 0x1c, 0xfe, 0x60, 0x1f, 0xa7, 0xc4, + 0x03, 0xf3, 0xc8, 0x07, 0x80, + + /* U+0025 "%" */ + 0x02, 0xcf, 0xd5, 0x00, 0xc9, 0xf4, 0x1d, 0xad, + 0x9e, 0x60, 0x17, 0x70, 0x57, 0xd4, 0x0b, 0xe4, + 0x01, 0x3e, 0xc1, 0x1e, 0x40, 0x0f, 0xa0, 0x3f, + 0xb0, 0x03, 0xfa, 0x01, 0x7c, 0x86, 0xf9, 0x00, + 0x0f, 0xec, 0xeb, 0xd1, 0xfd, 0xc0, 0x34, 0x7f, + 0xd0, 0x5f, 0xa0, 0x1e, 0x24, 0x20, 0xbf, 0x30, + 0x0f, 0xe6, 0xf8, 0x00, 0xfe, 0x1e, 0xe0, 0x07, + 0xfa, 0xbd, 0x0a, 0xff, 0x58, 0x03, 0x27, 0xd0, + 0x77, 0xce, 0xfa, 0x00, 0x5b, 0xc2, 0xbe, 0xc0, + 0x5f, 0x40, 0x08, 0xf6, 0x07, 0xf3, 0x00, 0x7d, + 0x81, 0xfd, 0x80, 0x1b, 0xd4, 0x07, 0xe4, 0x33, + 0xc8, 0x00, 0x3f, 0xad, 0x7e, 0x4f, 0xee, 0x01, + 0x8f, 0x3f, 0x50, 0x00, + + /* U+0026 "&" */ + 0x00, 0x8e, 0xff, 0xd8, 0x60, 0x1f, 0x17, 0xfb, + 0x75, 0xfe, 0x30, 0x0f, 0x57, 0xc8, 0x02, 0x3e, + 0xc0, 0x3d, 0xde, 0x40, 0x03, 0xfd, 0x00, 0xf7, + 0xf8, 0xc0, 0x09, 0xfa, 0x01, 0xed, 0xf7, 0x00, + 0x5f, 0xc0, 0x07, 0x9f, 0xf8, 0xaf, 0xf4, 0x03, + 0xf6, 0xff, 0xd8, 0x20, 0x1f, 0x0e, 0x7f, 0xac, + 0x03, 0xf1, 0x77, 0xef, 0xf8, 0xc0, 0x7f, 0xc0, + 0x16, 0x7c, 0x85, 0xff, 0x09, 0x7f, 0x00, 0x0b, + 0xfc, 0x01, 0x6f, 0xe2, 0xfd, 0x80, 0x13, 0xf4, + 0x02, 0x2f, 0xfc, 0xe0, 0x03, 0xff, 0x00, 0x65, + 0xff, 0x84, 0x02, 0xef, 0x80, 0x08, 0xbb, 0xfc, + 0x60, 0x12, 0xff, 0xb6, 0x6f, 0xfd, 0xdf, 0xc2, + 0x01, 0x1d, 0xf7, 0xf5, 0x20, 0xef, 0xe0, 0x00, + + /* U+0027 "'" */ + 0xbf, 0xea, 0xfd, 0x9f, 0xc8, 0xfb, 0x7f, 0xa3, + 0x84, + + /* U+0028 "(" */ + 0x00, 0xe1, 0x10, 0x07, 0x0e, 0xe8, 0x03, 0xb7, + 0xdc, 0x03, 0x57, 0xc8, 0x06, 0x5f, 0xd0, 0x0e, + 0xef, 0x40, 0x0c, 0xdf, 0x60, 0x1d, 0x9e, 0xa0, + 0x18, 0x7f, 0xc0, 0x1c, 0x9f, 0xa0, 0x1c, 0xdf, + 0x40, 0x1c, 0xff, 0x20, 0x1c, 0xff, 0x40, 0x1c, + 0xbf, 0x80, 0x1c, 0x7f, 0xc0, 0x1e, 0xef, 0x30, + 0x0e, 0x9f, 0x90, 0x0e, 0x3f, 0xf0, 0x80, 0x75, + 0x7c, 0x80, 0x70, 0xf7, 0xa0, 0x07, 0x2f, 0xf1, + 0x00, 0x73, 0xfe, 0x80, 0x79, 0xd4, 0x00, + + /* U+0029 ")" */ + 0x03, 0x00, 0xea, 0xf4, 0x00, 0xc9, 0xfe, 0x20, + 0x0c, 0xff, 0xa0, 0x1d, 0x7f, 0x20, 0x18, 0x7f, + 0xc4, 0x01, 0xa7, 0xe4, 0x03, 0x17, 0xf8, 0x03, + 0xb7, 0xd0, 0x03, 0x57, 0xb8, 0x06, 0x8f, 0x90, + 0x0c, 0xff, 0x40, 0x19, 0xfe, 0x80, 0x34, 0x7c, + 0x00, 0x6b, 0xf5, 0x00, 0xdf, 0xe1, 0x00, 0x97, + 0xf0, 0x03, 0x67, 0xa8, 0x04, 0xbf, 0x80, 0x10, + 0xf7, 0x98, 0x05, 0x9e, 0xe0, 0x15, 0x7c, 0x80, + 0x63, 0x90, 0x0e, + + /* U+002A "*" */ + 0x00, 0xc7, 0xec, 0x01, 0xf8, 0xbd, 0x40, 0x3a, + 0xa8, 0x22, 0xf4, 0x09, 0xd0, 0x03, 0xf7, 0x17, + 0xdb, 0x7e, 0x44, 0x02, 0x7e, 0xff, 0x48, 0x80, + 0x61, 0x8f, 0xfa, 0x48, 0x02, 0x8f, 0xe4, 0xf6, + 0xcf, 0xa1, 0x0a, 0x90, 0x1f, 0x40, 0x7c, 0x00, + 0xe2, 0xf5, 0x00, 0xfc, 0x7e, 0xc0, 0x18, + + /* U+002B "+" */ + 0x00, 0xe6, 0xf9, 0x00, 0xff, 0x37, 0xc8, 0x07, + 0xf9, 0xbe, 0x40, 0x3f, 0xcd, 0xf2, 0x01, 0xfe, + 0x6f, 0x90, 0x0f, 0x7f, 0xff, 0xc6, 0x19, 0x9b, + 0x7f, 0xb3, 0x31, 0x00, 0x73, 0x7c, 0x80, 0x7f, + 0x9b, 0xe4, 0x03, 0xfc, 0xdf, 0x20, 0x1f, 0xe6, + 0xf9, 0x00, 0xff, 0x12, 0x98, 0x07, 0x00, + + /* U+002C "," */ + 0x00, 0xab, 0xa0, 0x02, 0x2f, 0xf8, 0xc0, 0x2e, + 0xff, 0x30, 0x04, 0xbf, 0xe6, 0x00, 0x8b, 0xfc, + 0x40, 0x15, 0x7d, 0x80, 0xd7, 0x7e, 0x88, 0x1f, + 0xe3, 0x80, 0x40, + + /* U+002D "-" */ + 0xde, 0xef, 0x0f, 0x7f, 0xf8, 0x40, + + /* U+002E "." */ + 0x09, 0xd9, 0x05, 0xff, 0x95, 0x5f, 0xf2, 0x85, + 0x7d, 0x00, + + /* U+002F "/" */ + 0x00, 0xff, 0x27, 0xd0, 0x07, 0xfb, 0xb8, 0x20, + 0x1f, 0xd3, 0xec, 0x01, 0xfc, 0x7f, 0x60, 0x1f, + 0xed, 0xf2, 0x00, 0xfe, 0x7f, 0x70, 0x0f, 0xe2, + 0xfd, 0x00, 0xff, 0x5f, 0x98, 0x07, 0xf3, 0x7c, + 0x00, 0x7f, 0x0f, 0x70, 0x03, 0xfd, 0x5e, 0x80, + 0x1f, 0xc9, 0xf4, 0x01, 0xfe, 0xde, 0x10, 0x0f, + 0xe8, 0xf6, 0x00, 0xfe, 0x3f, 0xb0, 0x0f, 0xf6, + 0x79, 0x00, 0x7f, 0x3f, 0xb8, 0x07, 0xf8, + + /* U+0030 "0" */ + 0x00, 0x0c, 0x6f, 0xf5, 0x98, 0x06, 0x1e, 0xff, + 0x67, 0x7f, 0x98, 0x02, 0xcf, 0xa0, 0x0a, 0x3f, + 0xc4, 0x09, 0xfc, 0x01, 0xd7, 0xf0, 0x13, 0xf0, + 0x01, 0xd7, 0xfa, 0x19, 0xe8, 0x01, 0x16, 0xff, + 0xc1, 0xde, 0x40, 0x06, 0xff, 0x3f, 0xf8, 0x7f, + 0xc2, 0x15, 0xfa, 0x61, 0xde, 0x5d, 0xeb, 0xbf, + 0x00, 0x17, 0x78, 0xef, 0xfb, 0x90, 0x03, 0x7f, + 0x82, 0xbf, 0x04, 0x03, 0x27, 0xe0, 0x2f, 0xf0, + 0x07, 0x5f, 0xb8, 0x03, 0x7e, 0x80, 0x27, 0xfe, + 0x10, 0x01, 0xff, 0xd9, 0xdf, 0xe4, 0x00, 0xc5, + 0x5d, 0xfd, 0x44, 0x01, 0x00, + + /* U+0031 "1" */ + 0x00, 0x86, 0x3f, 0xc8, 0x01, 0xcf, 0xff, 0x90, + 0x02, 0x3e, 0xff, 0x47, 0xf9, 0x00, 0x37, 0x40, + 0x87, 0xf9, 0x00, 0x3f, 0x7f, 0x90, 0x03, 0xf7, + 0xf9, 0x00, 0x3f, 0x7f, 0x90, 0x03, 0xf7, 0xf9, + 0x00, 0x3f, 0x7f, 0x90, 0x03, 0xf7, 0xf9, 0x00, + 0x3f, 0x7f, 0x90, 0x03, 0xf7, 0xf9, 0x00, 0x3f, + 0x7f, 0x90, 0x03, 0x6f, 0x75, 0xfe, 0xee, 0xa4, + 0x3f, 0xff, 0xac, + + /* U+0032 "2" */ + 0x00, 0x25, 0x77, 0xf4, 0x88, 0x05, 0x3f, 0xee, + 0xe7, 0xfb, 0x84, 0x01, 0x9a, 0x60, 0x02, 0xef, + 0xa0, 0x00, 0x80, 0x73, 0x7f, 0x00, 0x7e, 0x3f, + 0xf0, 0x07, 0xe5, 0xfd, 0x00, 0xfd, 0x9e, 0xe0, + 0x1f, 0x3f, 0xe8, 0x07, 0xcd, 0xfc, 0x40, 0x1e, + 0x6f, 0xe3, 0x00, 0xf3, 0xff, 0x18, 0x07, 0xa3, + 0xf8, 0x80, 0x3d, 0x3f, 0xa2, 0x01, 0xe4, 0xff, + 0xfe, 0xc4, 0xff, 0xfe, 0xd0, + + /* U+0033 "3" */ + 0x05, 0xbe, 0xff, 0x6c, 0x88, 0x05, 0x5f, 0xb9, + 0xbf, 0xee, 0x20, 0x01, 0x00, 0x61, 0xdf, 0xa0, + 0x0f, 0xcd, 0xf6, 0x01, 0xfa, 0x3e, 0x00, 0x3c, + 0x2f, 0xfa, 0x20, 0x11, 0xff, 0xec, 0x10, 0x0c, + 0x55, 0x4c, 0xff, 0x71, 0x80, 0x7e, 0x8f, 0xe1, + 0x00, 0xfd, 0x9e, 0xc0, 0x1f, 0xab, 0xdc, 0x03, + 0xf7, 0x7a, 0x00, 0x78, 0xaf, 0xf0, 0x07, 0xf7, + 0x31, 0xdf, 0xec, 0x10, 0x06, 0xff, 0xdd, 0x6a, + 0x01, 0x00, + + /* U+0034 "4" */ + 0x00, 0xf2, 0x7f, 0xc0, 0x1f, 0xdd, 0xff, 0x00, + 0x7e, 0x9f, 0xaf, 0xf0, 0x07, 0xc9, 0xfa, 0x5f, + 0xe0, 0x0f, 0xb7, 0xcc, 0xbf, 0xc0, 0x1e, 0x9f, + 0x80, 0x2f, 0xf0, 0x07, 0x1f, 0xe8, 0x00, 0xbf, + 0xc0, 0x1d, 0xbe, 0x60, 0x02, 0xff, 0x00, 0x68, + 0xf8, 0x00, 0x8b, 0xfc, 0x01, 0x1f, 0xe8, 0x06, + 0x2f, 0xf0, 0x05, 0x1f, 0xff, 0xf4, 0xb6, 0x67, + 0xb7, 0xfd, 0x98, 0x70, 0x0f, 0x8b, 0xfc, 0x01, + 0xfe, 0x2f, 0xf0, 0x07, 0xf8, 0xbf, 0xc0, 0x10, + + /* U+0035 "5" */ + 0xaf, 0xff, 0xa4, 0x2b, 0xf7, 0x33, 0x9c, 0x2b, + 0xd0, 0x03, 0xea, 0xf4, 0x00, 0xfa, 0xbd, 0x00, + 0x3e, 0xaf, 0xdb, 0xa8, 0x40, 0x0a, 0xbf, 0xfd, + 0xa4, 0x01, 0xc4, 0xdb, 0xfa, 0x01, 0xf0, 0xff, + 0x90, 0x03, 0xec, 0xf6, 0x00, 0xfb, 0x7d, 0x40, + 0x3c, 0x7f, 0xe1, 0x00, 0xe5, 0xef, 0x70, 0xed, + 0xcc, 0x77, 0xfa, 0x00, 0x19, 0xff, 0x6c, 0x98, + 0x04, + + /* U+0036 "6" */ + 0x00, 0xc9, 0x5b, 0xfe, 0xd0, 0x08, 0x73, 0xfe, + 0xdc, 0xa0, 0x0b, 0x7e, 0x8c, 0x03, 0xd1, 0xf0, + 0x01, 0xfb, 0xf8, 0x03, 0xf1, 0xfd, 0x0b, 0x4d, + 0x41, 0x80, 0x1b, 0xfb, 0xff, 0xd2, 0x0f, 0xfe, + 0x93, 0x01, 0x6f, 0xf3, 0x47, 0xc8, 0x07, 0x3f, + 0xe4, 0x7c, 0x80, 0x71, 0xff, 0x9b, 0xf0, 0x03, + 0x8f, 0xfc, 0x5f, 0xe1, 0x00, 0xcf, 0xf6, 0x19, + 0xf4, 0x01, 0x1f, 0x7a, 0x01, 0x77, 0xf5, 0xe7, + 0xf9, 0xc0, 0x22, 0x9e, 0xfe, 0xb4, 0x00, 0x00, + + /* U+0037 "7" */ + 0xaf, 0xff, 0xeb, 0x9e, 0xef, 0xbf, 0xd6, 0x01, + 0xfa, 0xbd, 0xc0, 0x3e, 0x2f, 0xe0, 0x0f, 0xd5, + 0xee, 0x01, 0xf1, 0xff, 0x00, 0x7e, 0xbf, 0x70, + 0x0f, 0x8f, 0xf8, 0x03, 0xf5, 0xfb, 0x80, 0x7c, + 0x7f, 0xe1, 0x00, 0xfa, 0xfe, 0x00, 0x3e, 0x3f, + 0xf0, 0x80, 0x7d, 0x7f, 0x00, 0x1f, 0x27, 0xf8, + 0x40, 0x3e, 0xcf, 0x80, 0x0f, 0x00, + + /* U+0038 "8" */ + 0x00, 0x1d, 0x77, 0xfb, 0x1c, 0x02, 0x6f, 0xf6, + 0xde, 0x7f, 0xb0, 0x07, 0xfc, 0x80, 0x11, 0x77, + 0xa9, 0xff, 0x00, 0x75, 0x7b, 0x17, 0xf8, 0x80, + 0x36, 0xfa, 0x05, 0x7f, 0x20, 0x0d, 0xfd, 0x80, + 0x55, 0xfe, 0xdf, 0xf4, 0x80, 0x61, 0xcf, 0xfb, + 0x94, 0x02, 0x4f, 0xf5, 0x25, 0x7f, 0xa4, 0x07, + 0xfc, 0xc0, 0x12, 0xff, 0x95, 0xfe, 0xc0, 0x3a, + 0x7e, 0xe7, 0xe8, 0x03, 0x9f, 0xf1, 0xbf, 0xca, + 0x01, 0x1f, 0x7c, 0x06, 0x7f, 0xbb, 0x37, 0xfd, + 0x80, 0x13, 0x67, 0x7f, 0x5b, 0x00, 0x00, + + /* U+0039 "9" */ + 0x00, 0x1d, 0x77, 0xf5, 0x10, 0x04, 0xdf, 0xed, + 0xbe, 0xff, 0x18, 0x1f, 0xf9, 0x00, 0x27, 0xfd, + 0x0a, 0xf8, 0x00, 0xed, 0xf4, 0xcf, 0x50, 0x0e, + 0x8f, 0x8c, 0xf7, 0x00, 0xe6, 0xfa, 0x7f, 0xe2, + 0x00, 0x86, 0xbe, 0xc3, 0x7f, 0xd9, 0x59, 0xff, + 0x50, 0x02, 0x37, 0xfd, 0xaf, 0x1f, 0x20, 0x1f, + 0xa7, 0xd8, 0x03, 0xf7, 0x79, 0x00, 0x7d, 0x3f, + 0x60, 0x1e, 0x3b, 0xfe, 0x10, 0x05, 0xe6, 0xff, + 0xda, 0x40, 0x17, 0x7f, 0x6d, 0x28, 0x06, + + /* U+003A ":" */ + 0x08, 0xfb, 0x01, 0xff, 0x94, 0x3f, 0xe3, 0x03, + 0x84, 0x00, 0xff, 0xe5, 0x1c, 0x20, 0x03, 0xfe, + 0x31, 0xff, 0x94, 0x23, 0xec, 0x00, + + /* U+003B ";" */ + 0x00, 0xa3, 0xec, 0x02, 0x1f, 0xf9, 0x40, 0x2f, + 0xf8, 0xc0, 0x23, 0x84, 0x00, 0xff, 0xea, 0x35, + 0xb0, 0x06, 0xff, 0x90, 0x02, 0xdf, 0xf4, 0x00, + 0x49, 0xfe, 0x80, 0x0d, 0xfe, 0x50, 0x0a, 0x3f, + 0x40, 0x15, 0xbf, 0xc4, 0x00, 0xfd, 0x81, 0x00, + 0x00, + + /* U+003C "<" */ + 0x00, 0xf8, 0xec, 0x40, 0x3c, 0xbf, 0xe7, 0x00, + 0xe7, 0xff, 0x28, 0x07, 0x57, 0xf1, 0x80, 0x61, + 0xcf, 0xc1, 0x00, 0xc5, 0xdf, 0x40, 0x1c, 0x5f, + 0xea, 0x00, 0xf9, 0x7f, 0xce, 0x01, 0xf1, 0xf7, + 0xd0, 0x07, 0xc3, 0xbf, 0x82, 0x01, 0xf5, 0xff, + 0x18, 0x07, 0xd1, 0xfe, 0x50, 0x0f, 0x97, 0x8c, + 0x03, 0xfc, + + /* U+003D "=" */ + 0x5b, 0xbf, 0xe7, 0x77, 0xff, 0xf5, 0x00, 0x7f, + 0xf2, 0x96, 0xef, 0xf9, 0xdd, 0xff, 0xfd, 0x40, + + /* U+003E ">" */ + 0x0a, 0x50, 0x0f, 0x93, 0xfc, 0xe0, 0x1f, 0x1f, + 0x7d, 0x00, 0x7c, 0x39, 0xf8, 0x20, 0x1f, 0x57, + 0xf1, 0x00, 0x7d, 0x1f, 0xe4, 0x00, 0xf9, 0xff, + 0xc8, 0x01, 0xc9, 0xfe, 0x80, 0x0e, 0x7f, 0xf2, + 0x80, 0x74, 0xff, 0x18, 0x06, 0x1c, 0xfd, 0x10, + 0x0c, 0x5d, 0xf6, 0x01, 0xe1, 0xd8, 0x00, 0xff, + 0xe2, 0x80, + + /* U+003F "?" */ + 0x7e, 0xd9, 0x30, 0x09, 0xbb, 0xfe, 0x90, 0x0e, + 0x7e, 0xfa, 0x00, 0xe2, 0xff, 0x20, 0x07, 0x4f, + 0xd0, 0x07, 0x3f, 0xe0, 0x07, 0x47, 0xd8, 0x06, + 0x5f, 0xf3, 0x02, 0x7f, 0xeb, 0x00, 0x1f, 0xeb, + 0x98, 0x04, 0x7f, 0x40, 0x1c, 0x5f, 0x20, 0x1e, + 0x53, 0x00, 0xff, 0xe0, 0xb7, 0xe0, 0x07, 0x67, + 0xf8, 0xc0, 0x32, 0xf5, 0x80, 0x60, + + /* U+0040 "@" */ + 0x00, 0xe7, 0xdf, 0xe9, 0x10, 0x0f, 0x16, 0xfd, + 0x3c, 0xff, 0x10, 0x06, 0x1d, 0xe3, 0x00, 0x8b, + 0xf0, 0x03, 0x57, 0xa0, 0x07, 0x3f, 0xa0, 0x00, + 0xbe, 0x80, 0x3c, 0x5f, 0x00, 0x09, 0xf3, 0x00, + 0xfb, 0xb0, 0x01, 0xf8, 0x01, 0x33, 0xa3, 0x06, + 0x70, 0x1f, 0xb8, 0x0e, 0xff, 0xdc, 0x15, 0xe0, + 0xde, 0x81, 0x7e, 0xa7, 0xf8, 0x15, 0xe1, 0x5e, + 0x25, 0xf6, 0x07, 0xf2, 0x15, 0xe1, 0x7e, 0x0d, + 0xec, 0x0d, 0xee, 0x15, 0xe1, 0x9a, 0x13, 0xe6, + 0x11, 0xe8, 0x19, 0xa1, 0xb8, 0x15, 0xe4, 0x15, + 0xe4, 0x1d, 0x61, 0xb8, 0x15, 0xe4, 0x1d, 0xe0, + 0x5e, 0xe1, 0x9a, 0x11, 0xea, 0xff, 0xe2, 0x9f, + 0x20, 0xbf, 0x03, 0xff, 0x9b, 0xfe, 0x80, 0x04, + 0xf9, 0x01, 0xb9, 0x82, 0x3a, 0x00, 0x4b, 0xec, + 0x01, 0xff, 0xc0, 0xfd, 0x00, 0xff, 0xe0, 0x47, + 0xc8, 0x07, 0x10, 0x07, 0xaf, 0xf6, 0x1e, 0x77, + 0xc0, 0x3e, 0x7c, 0xff, 0x6c, 0xa0, 0x06, + + /* U+0041 "A" */ + 0x00, 0xef, 0xf8, 0xc0, 0x3f, 0x93, 0xfe, 0x90, + 0x0f, 0xea, 0xf9, 0xfe, 0x00, 0xfe, 0xff, 0x0f, + 0x79, 0x80, 0x7c, 0xbf, 0x61, 0x5f, 0x20, 0x1f, + 0x57, 0xb0, 0x27, 0xf0, 0x07, 0xdf, 0xe1, 0x00, + 0x7f, 0x8c, 0x03, 0x97, 0xf0, 0x02, 0xaf, 0x90, + 0x0e, 0xaf, 0x70, 0x09, 0x7f, 0x80, 0x3b, 0xfc, + 0x40, 0x1b, 0xfc, 0x60, 0x12, 0xff, 0xff, 0x48, + 0x05, 0x7f, 0xdb, 0xbd, 0xdf, 0xc0, 0x17, 0xf8, + 0x80, 0x38, 0x7f, 0xc6, 0x0b, 0xf8, 0x01, 0xf5, + 0xfc, 0x85, 0xfb, 0x80, 0x7c, 0xbf, 0xc0, + + /* U+0042 "B" */ + 0x2f, 0xfe, 0xeb, 0x60, 0x01, 0x7f, 0xb3, 0x2e, + 0xff, 0x50, 0x17, 0xf8, 0x03, 0x3f, 0xf8, 0xcb, + 0xfc, 0x01, 0xdd, 0xea, 0x5f, 0xe0, 0x0e, 0xff, + 0x19, 0x7f, 0x80, 0x34, 0x7e, 0x01, 0x7f, 0xae, + 0xd9, 0xfe, 0x91, 0x02, 0xff, 0xfb, 0x94, 0x0b, + 0xfc, 0x01, 0x1c, 0xff, 0x90, 0xbf, 0xc0, 0x1d, + 0x3f, 0x65, 0xfe, 0x00, 0xe5, 0xfd, 0x2f, 0xf0, + 0x07, 0x47, 0xe1, 0x7f, 0x80, 0x32, 0x7f, 0x94, + 0xbf, 0xd9, 0x97, 0x7f, 0xa4, 0x0b, 0xff, 0xb6, + 0x8c, 0x00, + + /* U+0043 "C" */ + 0x00, 0x8a, 0x77, 0xfd, 0xb2, 0x60, 0x06, 0xff, + 0xbb, 0x9f, 0xea, 0x05, 0xff, 0x48, 0x80, 0x48, + 0xc1, 0xfe, 0x70, 0x0f, 0x9b, 0xf4, 0x03, 0xf5, + 0x7c, 0x00, 0x7e, 0xdf, 0x50, 0x0f, 0xdd, 0xe8, + 0x01, 0xfb, 0x7d, 0x40, 0x3f, 0x67, 0xc0, 0x07, + 0xe8, 0xfc, 0x00, 0xfc, 0x7f, 0xe5, 0x00, 0xfd, + 0x5f, 0xe7, 0x10, 0x09, 0x14, 0x01, 0x7f, 0xf7, + 0x73, 0xfd, 0x40, 0x12, 0xd7, 0x7f, 0x6c, 0x98, + + /* U+0044 "D" */ + 0xbf, 0xfd, 0xd6, 0xe2, 0x01, 0x5f, 0xee, 0x63, + 0xbf, 0xdc, 0x80, 0x0b, 0xf5, 0x00, 0x8a, 0xff, + 0xc4, 0x17, 0xea, 0x01, 0xd9, 0xf4, 0x17, 0xea, + 0x01, 0xc9, 0xfe, 0x0b, 0xf5, 0x00, 0xf7, 0xf8, + 0xef, 0xd4, 0x03, 0xdd, 0xe9, 0x7e, 0xa0, 0x1e, + 0xdf, 0x5b, 0xf5, 0x00, 0xf7, 0x79, 0xdf, 0xa8, + 0x07, 0x0f, 0xf8, 0xaf, 0xd4, 0x03, 0x9b, 0xf4, + 0x2f, 0xd4, 0x03, 0x0f, 0x7b, 0x85, 0xfa, 0x80, + 0x4b, 0xbf, 0x80, 0x0b, 0xfe, 0xdd, 0x7f, 0xd6, + 0x20, 0x0b, 0xff, 0xdb, 0x48, 0x01, 0x80, + + /* U+0045 "E" */ + 0xaf, 0xff, 0xc3, 0x5f, 0xb9, 0x9e, 0x0a, 0xf7, + 0x00, 0xfa, 0xbd, 0xc0, 0x3e, 0xaf, 0x70, 0x0f, + 0xab, 0xdc, 0x03, 0xea, 0xfd, 0xcc, 0xe9, 0x0a, + 0xff, 0xfb, 0x42, 0xbd, 0xc0, 0x3e, 0xaf, 0x70, + 0x0f, 0xab, 0xdc, 0x03, 0xea, 0xf7, 0x00, 0xfa, + 0xbd, 0xc0, 0x3e, 0xaf, 0xec, 0xcf, 0x05, 0x7f, + 0xfe, 0x10, + + /* U+0046 "F" */ + 0x9f, 0xff, 0xc1, 0x3f, 0xd9, 0x9e, 0x09, 0xf8, + 0x00, 0xfa, 0x7e, 0x00, 0x3e, 0x9f, 0x80, 0x0f, + 0xa7, 0xe0, 0x03, 0xe9, 0xfe, 0xcc, 0xe8, 0x09, + 0xff, 0xfa, 0xc2, 0x7e, 0x00, 0x3e, 0x9f, 0x80, + 0x0f, 0xa7, 0xe0, 0x03, 0xe9, 0xf8, 0x00, 0xfa, + 0x7e, 0x00, 0x3e, 0x9f, 0x80, 0x0f, 0xa7, 0xe0, + 0x03, 0xe0, + + /* U+0047 "G" */ + 0x00, 0xc5, 0x3b, 0xfe, 0xda, 0x40, 0x0a, 0x3f, + 0xee, 0xe7, 0xfb, 0x00, 0x13, 0xfe, 0x81, 0x00, + 0x91, 0xc0, 0xff, 0xc8, 0x01, 0xfa, 0xfe, 0x40, + 0x3f, 0xbf, 0xc6, 0x01, 0xf8, 0xbf, 0xc0, 0x11, + 0xdd, 0xe9, 0x3f, 0xf0, 0x04, 0xbf, 0xfb, 0x4b, + 0xfc, 0x01, 0xe3, 0xfd, 0x1f, 0xf1, 0x00, 0x71, + 0xfe, 0x86, 0xfb, 0x80, 0x71, 0xfe, 0x83, 0xff, + 0x08, 0x06, 0x3f, 0xd0, 0x06, 0xff, 0x28, 0x04, + 0x7f, 0xa0, 0x02, 0xdf, 0xfb, 0xb9, 0xfe, 0xd0, + 0x0c, 0xd7, 0xdf, 0xec, 0x83, + + /* U+0048 "H" */ + 0xbf, 0x60, 0x0e, 0x2f, 0xeb, 0xf6, 0x00, 0xe2, + 0xfe, 0xbf, 0x60, 0x0e, 0x2f, 0xeb, 0xf6, 0x00, + 0xe2, 0xfe, 0xbf, 0x60, 0x0e, 0x2f, 0xeb, 0xf6, + 0x00, 0xe2, 0xfe, 0xbf, 0xec, 0xce, 0xdf, 0xeb, + 0xff, 0xfe, 0xeb, 0xf6, 0x00, 0xe2, 0xfe, 0xbf, + 0x60, 0x0e, 0x2f, 0xeb, 0xf6, 0x00, 0xe2, 0xfe, + 0xbf, 0x60, 0x0e, 0x2f, 0xeb, 0xf6, 0x00, 0xe2, + 0xfe, 0xbf, 0x60, 0x0e, 0x2f, 0xeb, 0xf6, 0x00, + 0xe2, 0xfe, + + /* U+0049 "I" */ + 0xff, 0xfe, 0x3c, 0xcb, 0x7f, 0xb3, 0x22, 0x00, + 0x9f, 0xe8, 0x03, 0xe7, 0xfa, 0x00, 0xf9, 0xfe, + 0x80, 0x3e, 0x7f, 0xa0, 0x0f, 0x9f, 0xe8, 0x03, + 0xe7, 0xfa, 0x00, 0xf9, 0xfe, 0x80, 0x3e, 0x7f, + 0xa0, 0x0f, 0x9f, 0xe8, 0x03, 0xe7, 0xfa, 0x00, + 0xf9, 0xfe, 0x80, 0x36, 0x65, 0xdf, 0xd9, 0x91, + 0x7f, 0xff, 0x18, + + /* U+004A "J" */ + 0xaf, 0xff, 0x92, 0x37, 0x7b, 0xfc, 0x80, 0x1e, + 0xdf, 0x40, 0x0f, 0x6f, 0xa0, 0x07, 0xb7, 0xd0, + 0x03, 0xdb, 0xe8, 0x01, 0xed, 0xf4, 0x00, 0xf6, + 0xfa, 0x00, 0x7b, 0x7d, 0x00, 0x3d, 0xbe, 0x80, + 0x1e, 0xef, 0x40, 0x0e, 0x1f, 0xf1, 0x49, 0x80, + 0x55, 0xf8, 0x1b, 0xfd, 0xbf, 0xf1, 0x82, 0x5f, + 0x7f, 0x51, 0x00, 0x00, + + /* U+004B "K" */ + 0x2f, 0xe0, 0x0e, 0xdf, 0x90, 0x2f, 0xe0, 0x0d, + 0x5f, 0x60, 0x02, 0xfe, 0x00, 0x9f, 0xf4, 0x02, + 0x2f, 0xe0, 0x02, 0x7f, 0x08, 0x04, 0x5f, 0xc0, + 0x5f, 0xe3, 0x00, 0xc5, 0xfc, 0x1b, 0xea, 0x01, + 0xc5, 0xfd, 0x7e, 0xe0, 0x1e, 0x2f, 0xfc, 0x80, + 0x1e, 0x2f, 0xe6, 0xfe, 0x20, 0x0e, 0x2f, 0xe0, + 0xaf, 0xd0, 0x0e, 0x2f, 0xe0, 0x06, 0xfd, 0x00, + 0x62, 0xfe, 0x00, 0x17, 0xf9, 0xc0, 0x22, 0xfe, + 0x00, 0x93, 0xfc, 0x80, 0x02, 0xfe, 0x00, 0xd1, + 0xfc, 0x40, 0x5f, 0xc0, 0x1d, 0x7f, 0xa0, + + /* U+004C "L" */ + 0x4f, 0xd0, 0x0f, 0x93, 0xf4, 0x03, 0xe4, 0xfd, + 0x00, 0xf9, 0x3f, 0x40, 0x3e, 0x4f, 0xd0, 0x0f, + 0x93, 0xf4, 0x03, 0xe4, 0xfd, 0x00, 0xf9, 0x3f, + 0x40, 0x3e, 0x4f, 0xd0, 0x0f, 0x93, 0xf4, 0x03, + 0xe4, 0xfd, 0x00, 0xf9, 0x3f, 0x40, 0x3e, 0x4f, + 0xd0, 0x0f, 0x93, 0xfd, 0x99, 0xe6, 0x4f, 0xff, + 0xd0, + + /* U+004D "M" */ + 0x0b, 0xff, 0x00, 0x76, 0xff, 0x00, 0x2f, 0xfc, + 0xa0, 0x11, 0xff, 0xc0, 0x0c, 0xef, 0xb0, 0x0a, + 0x7f, 0x7c, 0x01, 0xba, 0xbf, 0x10, 0x07, 0xd6, + 0x78, 0x03, 0xb5, 0x7d, 0xc1, 0xbd, 0x33, 0xc4, + 0x3f, 0x43, 0xf0, 0x33, 0x82, 0xfc, 0x83, 0xf0, + 0x2b, 0xd3, 0xe0, 0x2f, 0xcc, 0x3f, 0x01, 0x3f, + 0xbc, 0x82, 0xbd, 0x07, 0xec, 0x01, 0xbf, 0x80, + 0x0a, 0xf4, 0x2f, 0xb0, 0x03, 0xfb, 0x00, 0x27, + 0xd4, 0xfe, 0x80, 0x21, 0x00, 0xa7, 0xd8, 0xfe, + 0x80, 0x3e, 0x8f, 0x74, 0xf9, 0x00, 0xfa, 0x3e, + 0x17, 0xe4, 0x03, 0xe7, 0xf8, 0x6f, 0x80, 0x0f, + 0x9f, 0xe4, + + /* U+004E "N" */ + 0x9f, 0xf2, 0x80, 0x62, 0xfd, 0x9f, 0xf6, 0x00, + 0x62, 0xfd, 0x9f, 0xf9, 0x00, 0x22, 0xfd, 0x9f, + 0xaf, 0xc0, 0x08, 0xbf, 0x67, 0xd7, 0x7c, 0xc0, + 0x05, 0xfb, 0x3e, 0xaf, 0xf6, 0x00, 0x2f, 0xd9, + 0xf5, 0x0e, 0xf3, 0x02, 0xfd, 0x9f, 0x50, 0x7f, + 0xa0, 0x2f, 0xd9, 0xf5, 0x01, 0xff, 0x11, 0x3f, + 0x67, 0xd4, 0x01, 0x1f, 0x25, 0xfb, 0x3e, 0xa0, + 0x01, 0xff, 0x1f, 0xec, 0xfa, 0x80, 0x53, 0xf5, + 0xfb, 0x3e, 0xa0, 0x10, 0xff, 0xdb, 0x3e, 0xa0, + 0x1a, 0xbf, 0xdb, 0x3e, 0xa0, 0x18, 0xbf, 0xda, + + /* U+004F "O" */ + 0x00, 0x86, 0x77, 0xfa, 0xd4, 0x03, 0x8f, 0xbf, + 0xdb, 0xff, 0x48, 0x04, 0x3d, 0xf2, 0x20, 0x06, + 0xff, 0x30, 0x02, 0x3f, 0x00, 0x39, 0xff, 0x80, + 0x1d, 0xe8, 0x01, 0xef, 0xf1, 0x97, 0xf8, 0x03, + 0xec, 0xf6, 0x4f, 0xf0, 0x07, 0xd7, 0xee, 0xbf, + 0xa0, 0x1f, 0x57, 0xc2, 0x7f, 0x00, 0x7d, 0x7e, + 0xe7, 0xfe, 0x00, 0xfb, 0x7d, 0x43, 0xfc, 0x80, + 0x1c, 0x5f, 0xe2, 0x0b, 0xfa, 0x00, 0xe9, 0xfc, + 0x00, 0x1f, 0xfa, 0x00, 0x27, 0xff, 0x18, 0x04, + 0xff, 0xf6, 0xff, 0xcc, 0x01, 0xc7, 0x5d, 0xfd, + 0x44, 0x01, 0x00, + + /* U+0050 "P" */ + 0x2f, 0xfe, 0xea, 0x40, 0x01, 0x7f, 0xb3, 0x2f, + 0xfa, 0x40, 0xbf, 0xc0, 0x19, 0xbf, 0xcc, 0x5f, + 0xe0, 0x0e, 0x9f, 0xc2, 0xff, 0x00, 0x72, 0xff, + 0x17, 0xf8, 0x03, 0x9b, 0xf0, 0xbf, 0xc0, 0x1d, + 0x7f, 0x05, 0xfe, 0x00, 0x09, 0xdf, 0xf0, 0x97, + 0xff, 0xda, 0x40, 0x5f, 0xec, 0xc5, 0xca, 0x80, + 0x45, 0xfe, 0x00, 0xfc, 0x5f, 0xe0, 0x0f, 0xc5, + 0xfe, 0x00, 0xfc, 0x5f, 0xe0, 0x0f, 0xc5, 0xfe, + 0x00, 0xfc, + + /* U+0051 "Q" */ + 0x00, 0x86, 0x37, 0xfa, 0xd4, 0x03, 0xc5, 0xdf, + 0xee, 0xff, 0xa4, 0x03, 0xb7, 0xe8, 0x40, 0x0f, + 0xfe, 0x50, 0x09, 0xff, 0x40, 0x3a, 0x3f, 0x40, + 0x2d, 0xf5, 0x00, 0xe1, 0xff, 0x10, 0x0f, 0xf8, + 0x40, 0x3d, 0xbe, 0xa0, 0x7f, 0xe0, 0x0f, 0xaf, + 0xdc, 0x13, 0xf4, 0x03, 0xea, 0xf8, 0x04, 0xfd, + 0x00, 0xfa, 0xbe, 0x01, 0x3f, 0xc0, 0x1f, 0x67, + 0xb0, 0x17, 0xf8, 0x40, 0x3d, 0xde, 0x60, 0x0e, + 0xf6, 0x00, 0xe3, 0xff, 0x00, 0x53, 0xfa, 0x01, + 0xd9, 0xf2, 0x01, 0x0f, 0x7e, 0x20, 0x9d, 0xff, + 0x08, 0x06, 0x3e, 0xff, 0xed, 0x20, 0x0f, 0x0b, + 0xef, 0xe3, 0x00, 0x7f, 0x9b, 0xec, 0x03, 0xfe, + 0x1f, 0xf3, 0x88, 0x95, 0x80, 0x3e, 0x5f, 0xfe, + 0xe0, 0x0f, 0xc5, 0x37, 0x68, 0x20, + + /* U+0052 "R" */ + 0xff, 0xee, 0xa3, 0x00, 0xbf, 0xd9, 0x8d, 0xff, + 0x94, 0x01, 0xfe, 0x10, 0x0a, 0xbf, 0x80, 0x1f, + 0xe1, 0x00, 0x87, 0xfc, 0x21, 0xfe, 0x10, 0x08, + 0xbf, 0xc0, 0x0f, 0xf0, 0x80, 0x06, 0xfe, 0x80, + 0x1f, 0xeb, 0xac, 0xff, 0x60, 0x80, 0x3f, 0xfc, + 0xc0, 0x1b, 0xfc, 0x20, 0xff, 0xe2, 0x00, 0xbf, + 0xc2, 0x00, 0x9f, 0xb0, 0x0b, 0xfc, 0x20, 0x01, + 0xff, 0x18, 0x03, 0xfc, 0x20, 0x15, 0x7d, 0x00, + 0x3f, 0xc2, 0x01, 0x17, 0xf8, 0x83, 0xfc, 0x20, + 0x1a, 0xfe, 0x43, 0xfc, 0x20, 0x19, 0x3f, 0xc2, + + /* U+0053 "S" */ + 0x00, 0x14, 0xef, 0xfb, 0xb1, 0x80, 0x0d, 0xff, + 0x6e, 0xbb, 0xec, 0x0b, 0xfc, 0xe0, 0x18, 0x48, + 0x1f, 0xf0, 0x03, 0xf3, 0xfe, 0x80, 0x7e, 0x2f, + 0xf5, 0x08, 0x07, 0xc9, 0xdf, 0xe9, 0x30, 0x0f, + 0x0c, 0x77, 0xfb, 0x54, 0x03, 0xe5, 0xcf, 0xf4, + 0x80, 0x7e, 0x5f, 0xf2, 0x80, 0x7e, 0x9f, 0xa0, + 0x0f, 0xd5, 0xf2, 0x86, 0x01, 0xcd, 0xfe, 0x4b, + 0xff, 0x76, 0xf7, 0xfd, 0x00, 0xd7, 0xbf, 0xee, + 0xc9, 0x30, 0x00, + + /* U+0054 "T" */ + 0xff, 0xff, 0x8f, 0x33, 0x77, 0xf6, 0x66, 0x20, + 0x0c, 0xff, 0x40, 0x1f, 0xcf, 0xf4, 0x01, 0xfc, + 0xff, 0x40, 0x1f, 0xcf, 0xf4, 0x01, 0xfc, 0xff, + 0x40, 0x1f, 0xcf, 0xf4, 0x01, 0xfc, 0xff, 0x40, + 0x1f, 0xcf, 0xf4, 0x01, 0xfc, 0xff, 0x40, 0x1f, + 0xcf, 0xf4, 0x01, 0xfc, 0xff, 0x40, 0x1f, 0xcf, + 0xf4, 0x01, 0xfc, 0xff, 0x40, 0x1c, + + /* U+0055 "U" */ + 0xbf, 0x50, 0x0e, 0x2f, 0xf5, 0xfa, 0x80, 0x71, + 0x7f, 0xaf, 0xd4, 0x03, 0x8b, 0xfd, 0x7e, 0xa0, + 0x1c, 0x5f, 0xeb, 0xf5, 0x00, 0xe2, 0xff, 0x5f, + 0xa8, 0x07, 0x17, 0xfa, 0xfd, 0x40, 0x38, 0xbf, + 0xd7, 0xea, 0x01, 0xc5, 0xfe, 0xbf, 0x50, 0x0e, + 0x2f, 0xf5, 0xfa, 0x80, 0x71, 0x7f, 0x57, 0xb8, + 0x07, 0x27, 0xec, 0x7d, 0x00, 0x74, 0x7d, 0x1f, + 0xf9, 0x40, 0x24, 0xff, 0x20, 0x4f, 0xfb, 0xb3, + 0xbf, 0xd0, 0x01, 0x2d, 0xf7, 0xf5, 0xa0, 0x00, + + /* U+0056 "V" */ + 0xcf, 0x90, 0x0f, 0x8f, 0xfc, 0x0f, 0xfc, 0x01, + 0xf4, 0xfd, 0x00, 0xff, 0x8c, 0x03, 0xdd, 0xe8, + 0x00, 0xcf, 0x80, 0x0e, 0x3f, 0xe0, 0x09, 0xbf, + 0x40, 0x3a, 0x3e, 0x40, 0x21, 0xff, 0x18, 0x06, + 0xef, 0x30, 0x0d, 0x7f, 0x00, 0x11, 0xff, 0x00, + 0x73, 0x7e, 0x80, 0x51, 0xf0, 0x01, 0xc3, 0xfe, + 0x20, 0x06, 0xf9, 0x80, 0x7a, 0xfe, 0x00, 0xff, + 0x40, 0x3e, 0x6f, 0xd0, 0x8f, 0x80, 0x0f, 0x87, + 0xfc, 0x5b, 0xe4, 0x01, 0xfa, 0xfe, 0xbf, 0x40, + 0x3f, 0x97, 0xfe, 0x70, 0x0f, 0xf7, 0xfc, 0x40, + 0x1c, + + /* U+0057 "W" */ + 0x7f, 0x80, 0x0f, 0x8f, 0xe9, 0x7e, 0x40, 0x3e, + 0x4f, 0x94, 0xfa, 0x00, 0xf9, 0x7d, 0xcf, 0xec, + 0x03, 0xe6, 0xf6, 0x2f, 0xc0, 0x0f, 0x9f, 0xd4, + 0x7f, 0x40, 0x09, 0xcc, 0x00, 0x7f, 0x40, 0xfe, + 0x00, 0x4f, 0xe0, 0x02, 0x3c, 0xc3, 0xf8, 0x01, + 0xdf, 0xe2, 0x09, 0xf2, 0x0e, 0xf0, 0x4f, 0xaf, + 0x80, 0xaf, 0x10, 0xcf, 0x09, 0xf1, 0xfe, 0x0b, + 0xf0, 0x05, 0xf9, 0x75, 0x85, 0x79, 0xe7, 0x80, + 0x2b, 0xdb, 0xd8, 0x17, 0xe7, 0x78, 0x01, 0x3f, + 0x9e, 0x20, 0x0e, 0xfd, 0xc0, 0x04, 0x7f, 0xac, + 0x02, 0x9f, 0xf5, 0x80, 0x1f, 0xfc, 0xa0, 0x11, + 0xff, 0xa8, 0x00, + + /* U+0058 "X" */ + 0x1f, 0xf3, 0x00, 0x71, 0xff, 0x8c, 0x1b, 0xf8, + 0x40, 0x36, 0x7c, 0x00, 0x59, 0xf4, 0x01, 0x3f, + 0xe8, 0x06, 0x2f, 0xf2, 0x00, 0xff, 0x90, 0x03, + 0x9f, 0xf4, 0x2f, 0xe4, 0x03, 0xed, 0xfb, 0xfe, + 0x00, 0xfc, 0x7f, 0xf2, 0x00, 0x7f, 0x6f, 0xf8, + 0x40, 0x3f, 0x3f, 0xfd, 0x40, 0x1f, 0x17, 0xf9, + 0x7f, 0xca, 0x01, 0xec, 0xf9, 0x07, 0xfe, 0x10, + 0x0c, 0xff, 0xc0, 0x16, 0xfd, 0x00, 0x45, 0xfe, + 0x50, 0x09, 0x3f, 0xc8, 0x00, 0xcf, 0xb0, 0x0e, + 0xaf, 0xe0, 0x7f, 0xf1, 0x00, 0x70, 0xf7, 0xc8, + + /* U+0059 "Y" */ + 0xbf, 0xc0, 0x0f, 0x9f, 0xf8, 0x0b, 0xfc, 0xa0, + 0x1c, 0x3d, 0xea, 0x00, 0x8f, 0xe0, 0x0e, 0x8f, + 0xc0, 0x0d, 0xde, 0xe0, 0x10, 0xff, 0x8c, 0x03, + 0x37, 0xf8, 0x40, 0x15, 0xf2, 0x01, 0xec, 0xf9, + 0x02, 0xff, 0x08, 0x07, 0x8f, 0xfc, 0x37, 0xee, + 0x01, 0xfa, 0xbf, 0x3f, 0x40, 0x3f, 0x87, 0xfe, + 0x40, 0x0f, 0xf4, 0x7e, 0x00, 0x7f, 0xcf, 0xf4, + 0x01, 0xff, 0x3f, 0xd0, 0x07, 0xfc, 0xff, 0x40, + 0x1f, 0xf3, 0xfd, 0x00, 0x7f, 0xcf, 0xf4, 0x01, + 0xe0, + + /* U+005A "Z" */ + 0x7f, 0xff, 0xeb, 0x7e, 0xef, 0xbf, 0xd6, 0x01, + 0xf1, 0xff, 0x88, 0x03, 0xed, 0xf7, 0x00, 0xfa, + 0x7f, 0x00, 0x3e, 0x4f, 0xf1, 0x00, 0x78, 0x7b, + 0xd8, 0x03, 0xea, 0xfb, 0x00, 0xf9, 0x7f, 0x84, + 0x03, 0xc3, 0xde, 0xa0, 0x1f, 0x5f, 0xd0, 0x07, + 0xcd, 0xfc, 0x20, 0x1e, 0x1f, 0xf2, 0x00, 0x7d, + 0x5f, 0xff, 0xdb, 0x7f, 0xff, 0xdc, + + /* U+005B "[" */ + 0xff, 0xed, 0xff, 0x55, 0x51, 0xfe, 0x00, 0xdf, + 0xe0, 0x0d, 0xfe, 0x00, 0xdf, 0xe0, 0x0d, 0xfe, + 0x00, 0xdf, 0xe0, 0x0d, 0xfe, 0x00, 0xdf, 0xe0, + 0x0d, 0xfe, 0x00, 0xdf, 0xe0, 0x0d, 0xfe, 0x00, + 0xdf, 0xe0, 0x0d, 0xfe, 0x00, 0xdf, 0xe0, 0x0d, + 0xfe, 0x00, 0xdf, 0xe0, 0x0d, 0xfe, 0x00, 0xdf, + 0xe0, 0x0d, 0xfe, 0xaa, 0xa3, 0xff, 0xb4, + + /* U+005C "\\" */ + 0x0e, 0xf1, 0x00, 0xfc, 0xfe, 0xe0, 0x1f, 0x87, + 0xf4, 0x03, 0xfa, 0xbd, 0x00, 0x3f, 0x1f, 0xd8, + 0x07, 0xf6, 0x79, 0x00, 0x7e, 0x6f, 0x90, 0x0f, + 0xee, 0xf0, 0x0f, 0xe8, 0xf6, 0x00, 0xfc, 0x3f, + 0xa0, 0x1f, 0xd5, 0xe8, 0x01, 0xf9, 0x3e, 0xc0, + 0x3f, 0xb7, 0xc4, 0x03, 0xf3, 0x7c, 0x00, 0x7f, + 0x7f, 0x00, 0x7f, 0x4f, 0xb0, 0x07, 0xe2, 0xfc, + 0x00, 0xfe, 0xbf, 0x30, 0x0f, 0xc9, 0xf4, + + /* U+005D "]" */ + 0xaf, 0xfe, 0x26, 0xaa, 0xbb, 0xc8, 0x03, 0x6f, + 0x90, 0x06, 0xdf, 0x20, 0x0d, 0xbe, 0x40, 0x1b, + 0x7c, 0x80, 0x36, 0xf9, 0x00, 0x6d, 0xf2, 0x00, + 0xdb, 0xe4, 0x01, 0xb7, 0xc8, 0x03, 0x6f, 0x90, + 0x06, 0xdf, 0x20, 0x0d, 0xbe, 0x40, 0x1b, 0x7c, + 0x80, 0x36, 0xf9, 0x00, 0x6d, 0xf2, 0x00, 0xdb, + 0xe4, 0x01, 0xb7, 0xc8, 0x03, 0x6f, 0x90, 0x06, + 0xdf, 0x26, 0xaa, 0xbb, 0xca, 0xbf, 0xf8, 0x80, + + /* U+005E "^" */ + 0x00, 0xc7, 0x08, 0x01, 0xfb, 0x7f, 0x84, 0x03, + 0xcf, 0xf3, 0xf2, 0x01, 0xc3, 0xd6, 0x19, 0xe6, + 0x01, 0xa7, 0xc8, 0x0f, 0xf0, 0x02, 0x2f, 0x90, + 0x0a, 0x7d, 0x80, 0x17, 0xe2, 0x01, 0x0f, 0xf0, + 0xa7, 0xc0, 0x07, 0x3f, 0xc8, + + /* U+005F "_" */ + 0xbb, 0xff, 0xe0, 0x97, 0xff, 0xff, 0x04, 0xc0, + + /* U+0060 "`" */ + 0x0a, 0xa1, 0x07, 0xf8, 0x83, 0xfc, 0x21, 0xde, + 0x00, 0xdf, 0x00, 0x67, 0x00, + + /* U+0061 "a" */ + 0x02, 0x8c, 0xef, 0xec, 0x50, 0x09, 0xff, 0xdb, + 0x9d, 0xfe, 0x80, 0x01, 0xa0, 0x06, 0x6f, 0xf0, + 0x80, 0x7e, 0xdf, 0x30, 0x0f, 0xd9, 0xe8, 0x00, + 0x5b, 0xef, 0xfe, 0x40, 0xaf, 0xf5, 0xcc, 0xdd, + 0xe8, 0x7f, 0xe2, 0x00, 0xd9, 0xe8, 0xdf, 0x80, + 0x1d, 0xbe, 0x88, 0xfe, 0x10, 0x01, 0xef, 0xf9, + 0x03, 0x7f, 0xaf, 0x7f, 0x6f, 0xd0, 0x06, 0xbb, + 0xf6, 0x02, 0x7d, 0x00, + + /* U+0062 "b" */ + 0x2f, 0xe0, 0x0f, 0xc5, 0xfc, 0x01, 0xf8, 0xbf, + 0x80, 0x3f, 0x17, 0xf0, 0x07, 0xe2, 0xfe, 0x00, + 0xfc, 0x5f, 0xc0, 0xb9, 0xfd, 0x22, 0x05, 0xfb, + 0x3f, 0xed, 0xff, 0x60, 0x17, 0xfd, 0x20, 0x02, + 0xef, 0x52, 0xff, 0x40, 0x06, 0x8f, 0xa2, 0xfe, + 0x00, 0xe4, 0xfd, 0x2f, 0xe0, 0x0e, 0x3f, 0xe2, + 0xfe, 0x00, 0xe3, 0xfe, 0x2f, 0xe0, 0x0e, 0x5f, + 0xc2, 0xfe, 0x00, 0xea, 0xf7, 0x2f, 0xe0, 0x0c, + 0xdf, 0xc2, 0x5f, 0xf5, 0xdb, 0x7f, 0xc6, 0x00, + 0x5a, 0xdf, 0xf6, 0xc8, 0x80, 0x00, + + /* U+0063 "c" */ + 0x00, 0x8a, 0x77, 0xfd, 0xb2, 0x01, 0x27, 0xfd, + 0x9b, 0xfe, 0x00, 0x17, 0xfa, 0x40, 0x32, 0x00, + 0x2b, 0xec, 0x03, 0xf7, 0xf8, 0xc0, 0x3e, 0x1f, + 0xf0, 0x07, 0xe1, 0xff, 0x00, 0x7f, 0x7f, 0x88, + 0x03, 0xf6, 0x7c, 0x00, 0x7e, 0x5f, 0xf3, 0x00, + 0x64, 0x00, 0xa7, 0xfe, 0xcd, 0xff, 0x00, 0x64, + 0xbe, 0xfe, 0xc8, 0x00, + + /* U+0064 "d" */ + 0x00, 0xfd, 0x9e, 0x80, 0x1f, 0xb3, 0xd0, 0x03, + 0xf6, 0x7a, 0x00, 0x7e, 0xcf, 0x40, 0x0f, 0xd9, + 0xe8, 0x01, 0x3e, 0xff, 0xb7, 0xfc, 0x80, 0x5b, + 0xfd, 0x79, 0xdf, 0xe4, 0x0c, 0xf9, 0x00, 0xd9, + 0xe8, 0x8f, 0xd0, 0x0e, 0xcf, 0x48, 0xf8, 0x00, + 0xec, 0xf4, 0xaf, 0x60, 0x0e, 0xcf, 0x4a, 0xf5, + 0x00, 0xec, 0xf4, 0x9f, 0x70, 0x0e, 0xdf, 0x47, + 0xfa, 0x00, 0xcd, 0xfe, 0x42, 0xff, 0x10, 0x01, + 0x7f, 0xe4, 0x09, 0xfe, 0x9b, 0xfa, 0xa7, 0xa0, + 0x01, 0xfb, 0xf5, 0x82, 0x7d, 0x00, + + /* U+0065 "e" */ + 0x00, 0xa3, 0x7f, 0xad, 0x00, 0x21, 0xdf, 0xea, + 0xcf, 0xf3, 0x80, 0x2f, 0xe4, 0x02, 0x4f, 0xf1, + 0x97, 0xf0, 0x07, 0x47, 0xc3, 0xfc, 0x80, 0x72, + 0xfd, 0xcf, 0xff, 0xf6, 0x4f, 0xe4, 0xcf, 0xcf, + 0x1f, 0x40, 0x1f, 0x93, 0xf8, 0x03, 0xfb, 0x7e, + 0xc4, 0x03, 0xe3, 0xef, 0xf6, 0xde, 0x6f, 0x98, + 0x00, 0x63, 0x7f, 0xdd, 0x92, 0x20, + + /* U+0066 "f" */ + 0x00, 0xf1, 0xd7, 0x7f, 0xb4, 0xc0, 0x39, 0x3f, + 0xdd, 0x79, 0xca, 0x01, 0xdb, 0xf2, 0x01, 0xfc, + 0x5f, 0xe0, 0x0f, 0xf2, 0x7e, 0x80, 0x7f, 0x93, + 0xf0, 0x03, 0xfc, 0x9f, 0x80, 0x1e, 0x1f, 0xff, + 0xf8, 0x01, 0x77, 0x67, 0xfa, 0xef, 0x50, 0x07, + 0x27, 0xe0, 0x07, 0xf9, 0x3f, 0x00, 0x3f, 0xc9, + 0xf8, 0x01, 0xfe, 0x4f, 0xc0, 0x0f, 0xf2, 0x7e, + 0x00, 0x7f, 0x93, 0xf0, 0x03, 0xfc, 0x9f, 0x80, + 0x1f, 0xe4, 0xfc, 0x00, 0xf0, + + /* U+0067 "g" */ + 0x00, 0x15, 0x77, 0xff, 0x8c, 0x0f, 0xfd, 0x73, + 0x9f, 0xee, 0xe1, 0x86, 0xfb, 0x80, 0x51, 0xf4, + 0x00, 0x1f, 0xf0, 0x06, 0x1f, 0xf0, 0x00, 0xbf, + 0xc0, 0x18, 0x7f, 0xc0, 0x16, 0xfb, 0x00, 0x53, + 0xf6, 0x01, 0x37, 0xfa, 0xe7, 0x3f, 0x88, 0x02, + 0xdf, 0xae, 0xfe, 0x91, 0x00, 0x93, 0xe4, 0x03, + 0xf9, 0xbe, 0xc0, 0x3f, 0x8b, 0xfd, 0xd9, 0x9a, + 0x50, 0x02, 0x9f, 0xff, 0xd0, 0x0d, 0xfa, 0x20, + 0x10, 0xbf, 0xf8, 0x77, 0xd4, 0x03, 0xdf, 0xe2, + 0xdf, 0x90, 0x0e, 0x8f, 0xd0, 0x6f, 0xf7, 0x5d, + 0x5f, 0x7f, 0x18, 0x00, 0xeb, 0x7f, 0xdd, 0x90, + 0x20, 0x00, + + /* U+0068 "h" */ + 0x2f, 0xe0, 0x0f, 0xc5, 0xfc, 0x01, 0xf8, 0xbf, + 0x80, 0x3f, 0x17, 0xf0, 0x07, 0xe2, 0xfe, 0x00, + 0xfc, 0x5f, 0xc0, 0xdb, 0xfd, 0x00, 0x02, 0xfd, + 0x9f, 0xec, 0xff, 0x50, 0x17, 0xfd, 0x00, 0x04, + 0xff, 0x09, 0x7f, 0xa0, 0x03, 0x6f, 0xa1, 0x7f, + 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, 0x5f, 0xa9, + 0x7f, 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, 0x5f, + 0xa9, 0x7f, 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, + 0x5f, 0xa9, 0x7f, 0x00, 0x75, 0xfa, 0x97, 0xf0, + 0x07, 0x5f, 0xa8, + + /* U+0069 "i" */ + 0x00, 0x9f, 0xe8, 0x03, 0xef, 0xf8, 0x80, 0x3d, + 0x5f, 0xa0, 0x1f, 0x88, 0x03, 0xff, 0x87, 0x3f, + 0xfc, 0x01, 0x9a, 0xee, 0xff, 0x00, 0x7c, 0x3f, + 0xe0, 0x0f, 0x87, 0xfc, 0x01, 0xf0, 0xff, 0x80, + 0x3e, 0x1f, 0xf0, 0x07, 0xc3, 0xfe, 0x00, 0xf8, + 0x7f, 0xc0, 0x1f, 0x0f, 0xf8, 0x03, 0xe1, 0xff, + 0x00, 0x6b, 0xbd, 0xfe, 0xbb, 0x97, 0xff, 0xf9, + 0xc0, + + /* U+006A "j" */ + 0x00, 0xf3, 0xfd, 0x00, 0x7d, 0xff, 0x10, 0x07, + 0xab, 0xf4, 0x03, 0xf1, 0x00, 0x7f, 0xf0, 0x7f, + 0xfe, 0xd0, 0x05, 0x5d, 0xec, 0xfd, 0x00, 0xf8, + 0xff, 0x40, 0x3e, 0x3f, 0xd0, 0x0f, 0x8f, 0xf4, + 0x03, 0xe3, 0xfd, 0x00, 0xf8, 0xff, 0x40, 0x3e, + 0x3f, 0xd0, 0x0f, 0x8f, 0xf4, 0x03, 0xe3, 0xfd, + 0x00, 0xf8, 0xff, 0x40, 0x3e, 0x3f, 0xd0, 0x0f, + 0x93, 0xf0, 0x03, 0xe8, 0xf9, 0x03, 0x20, 0x08, + 0xff, 0xc8, 0x0f, 0xfd, 0x9b, 0xfe, 0x90, 0x01, + 0xdf, 0x7f, 0xb1, 0x40, 0x20, + + /* U+006B "k" */ + 0xdf, 0x20, 0x0f, 0xdb, 0xe4, 0x01, 0xfb, 0x7c, + 0x80, 0x3f, 0x6f, 0x90, 0x07, 0xed, 0xf2, 0x00, + 0xfd, 0xbe, 0x40, 0x11, 0x77, 0xd0, 0x6f, 0x90, + 0x00, 0x7b, 0xe8, 0x01, 0xbe, 0x40, 0x3b, 0xf4, + 0x01, 0x6f, 0x90, 0xef, 0xd0, 0x06, 0xdf, 0x3d, + 0xfa, 0x00, 0xed, 0xfc, 0xfd, 0x00, 0xf6, 0xfa, + 0x77, 0xc0, 0x07, 0x6f, 0x91, 0xff, 0x98, 0x03, + 0x6f, 0x90, 0x2f, 0xf9, 0x40, 0x2d, 0xf2, 0x00, + 0x3f, 0xf8, 0xc0, 0x1b, 0xe4, 0x01, 0x4f, 0xf1, + 0x06, 0xf9, 0x00, 0x6b, 0xfe, 0x10, + + /* U+006C "l" */ + 0x9f, 0xfe, 0x00, 0xcd, 0x54, 0xbf, 0xf0, 0x07, + 0xc3, 0xfe, 0x00, 0xf8, 0x7f, 0xc0, 0x1f, 0x0f, + 0xf8, 0x03, 0xe1, 0xff, 0x00, 0x7c, 0x3f, 0xe0, + 0x0f, 0x87, 0xfc, 0x01, 0xf0, 0xff, 0x80, 0x3e, + 0x1f, 0xf0, 0x07, 0xc3, 0xfe, 0x00, 0xf8, 0x7f, + 0xc0, 0x1f, 0x0f, 0xf8, 0x03, 0xe1, 0xff, 0x00, + 0x7c, 0x3f, 0xe0, 0x0d, 0x77, 0xbf, 0xd7, 0x72, + 0xff, 0xff, 0x38, + + /* U+006D "m" */ + 0xfa, 0x2c, 0xf8, 0x06, 0xed, 0x30, 0xfb, 0xdb, + 0xdf, 0x6f, 0x9f, 0xd0, 0xff, 0x68, 0x37, 0xf9, + 0x83, 0x3c, 0x3f, 0xc8, 0x0b, 0xfc, 0x00, 0xbf, + 0x2f, 0xf0, 0x01, 0x7e, 0x00, 0x17, 0xe5, 0xfe, + 0x00, 0x2f, 0xc0, 0x02, 0xfc, 0xbf, 0xc0, 0x05, + 0xf8, 0x00, 0x5f, 0x97, 0xf8, 0x00, 0xbf, 0x00, + 0x0b, 0xf2, 0xff, 0x00, 0x17, 0xe0, 0x01, 0x7e, + 0x5f, 0xe0, 0x02, 0xfc, 0x00, 0x2f, 0xcb, 0xfc, + 0x00, 0x5f, 0x80, 0x05, 0xf9, 0x7f, 0x80, 0x0b, + 0xf0, 0x00, 0xbf, 0x20, + + /* U+006E "n" */ + 0x2f, 0xb0, 0x7d, 0xfe, 0x90, 0x01, 0x7e, 0x5f, + 0xdc, 0xf7, 0xd0, 0x17, 0xfc, 0xa0, 0x02, 0xff, + 0x09, 0x7f, 0x94, 0x03, 0x67, 0xa1, 0x7f, 0x00, + 0x75, 0xfa, 0x97, 0xf0, 0x07, 0x5f, 0xa9, 0x7f, + 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, 0x5f, 0xa9, + 0x7f, 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, 0x5f, + 0xa9, 0x7f, 0x00, 0x75, 0xfa, 0x97, 0xf0, 0x07, + 0x5f, 0xa8, + + /* U+006F "o" */ + 0x00, 0x0c, 0xef, 0xf5, 0xa8, 0x06, 0x3f, 0xf7, + 0x66, 0xff, 0xa4, 0x00, 0x3d, 0xf0, 0x01, 0x27, + 0xf9, 0x41, 0xff, 0x00, 0x39, 0xff, 0x03, 0x3d, + 0x40, 0x38, 0xbf, 0xc1, 0xde, 0x60, 0x1e, 0xff, + 0x0f, 0x79, 0x80, 0x7b, 0xfc, 0x39, 0xea, 0x01, + 0xc5, 0xfe, 0x09, 0xfb, 0x00, 0xe9, 0xfa, 0x02, + 0xff, 0x30, 0x04, 0xdf, 0xe3, 0x00, 0x37, 0xfb, + 0xb3, 0x7f, 0xcc, 0x01, 0x8e, 0xbb, 0xfa, 0x8c, + 0x02, + + /* U+0070 "p" */ + 0x2f, 0xb0, 0x6c, 0xfe, 0x91, 0x02, 0xfc, 0xaf, + 0xc9, 0xdf, 0xc0, 0x2f, 0xf9, 0x80, 0x2d, 0xf5, + 0x2f, 0xf3, 0x00, 0x67, 0xfa, 0x2f, 0xe0, 0x0e, + 0x4f, 0xd2, 0xfe, 0x00, 0xe2, 0xfe, 0x2f, 0xe0, + 0x0e, 0x3f, 0xe2, 0xfe, 0x00, 0xe5, 0xfc, 0x2f, + 0xe0, 0x0e, 0xaf, 0x72, 0xfe, 0x00, 0xcd, 0xfc, + 0x25, 0xff, 0x65, 0x6f, 0xf1, 0x81, 0x7f, 0xb7, + 0xfd, 0xb2, 0x20, 0x02, 0xfe, 0x00, 0xfc, 0x5f, + 0xc0, 0x1f, 0x8b, 0xf8, 0x03, 0xf1, 0x7f, 0x00, + 0x7e, 0x2f, 0xe0, 0x0f, 0xc0, + + /* U+0071 "q" */ + 0x00, 0xff, 0xe1, 0x3e, 0xff, 0xb6, 0xb5, 0x00, + 0x77, 0xfa, 0xed, 0xdf, 0xe4, 0x0c, 0xf9, 0x00, + 0xd9, 0xe8, 0x8f, 0xd0, 0x0e, 0xcf, 0x48, 0xf8, + 0x00, 0xec, 0xf4, 0xaf, 0x60, 0x0e, 0xcf, 0x4a, + 0xf6, 0x00, 0xec, 0xf4, 0x9f, 0x70, 0x0e, 0xdf, + 0x47, 0xfb, 0x00, 0xd1, 0xfe, 0x42, 0xff, 0x20, + 0x02, 0x3f, 0xe4, 0x09, 0xff, 0x67, 0x7c, 0xdf, + 0xa0, 0x02, 0x3b, 0xf1, 0x43, 0x3d, 0x00, 0x3f, + 0x67, 0xa0, 0x07, 0xec, 0xf4, 0x00, 0xfd, 0x9e, + 0x80, 0x1f, 0xb3, 0xd0, 0x03, 0xf6, 0x7a, 0x00, + + /* U+0072 "r" */ + 0xaf, 0x30, 0x8d, 0xfd, 0x60, 0x05, 0x7b, 0x6f, + 0xd5, 0x3f, 0xca, 0x15, 0xfe, 0xe2, 0x00, 0x37, + 0xe0, 0x57, 0xf1, 0x00, 0x43, 0xfe, 0x0a, 0xf7, + 0x00, 0xe9, 0x90, 0x57, 0xb0, 0x07, 0xea, 0xf6, + 0x00, 0xfd, 0x5e, 0xc0, 0x1f, 0xab, 0xd8, 0x03, + 0xf5, 0x7b, 0x00, 0x7e, 0xaf, 0x60, 0x0f, 0xd5, + 0xec, 0x01, 0xf8, + + /* U+0073 "s" */ + 0x01, 0x8d, 0xff, 0x76, 0x20, 0x0f, 0x7f, 0x5d, + 0xb7, 0xd8, 0x23, 0xe8, 0x03, 0xea, 0xf7, 0x00, + 0xf9, 0xbf, 0xce, 0x20, 0x1e, 0x9f, 0xfb, 0x18, + 0x03, 0x8a, 0x37, 0xfd, 0xc8, 0x01, 0xe3, 0xbf, + 0xe0, 0x0f, 0xdf, 0xe2, 0x30, 0x0e, 0x4f, 0xf0, + 0x6f, 0xee, 0x63, 0x7f, 0xcc, 0x11, 0x9d, 0xfe, + 0xea, 0x30, 0x00, + + /* U+0074 "t" */ + 0x00, 0xcb, 0x20, 0x1f, 0xef, 0xf0, 0x80, 0x7f, + 0x7f, 0x84, 0x03, 0xfb, 0xfc, 0x20, 0x1c, 0x9f, + 0xff, 0xe5, 0x3b, 0xbb, 0xfd, 0x77, 0xc8, 0x01, + 0xbf, 0xc2, 0x01, 0xfd, 0xfe, 0x10, 0x0f, 0xef, + 0xf0, 0x80, 0x7f, 0x7f, 0x84, 0x03, 0xfb, 0xfc, + 0x20, 0x1f, 0xdf, 0xe1, 0x00, 0xfe, 0xef, 0x30, + 0x0f, 0xeb, 0xfb, 0x00, 0xfe, 0x4f, 0xf7, 0x66, + 0x39, 0x40, 0x39, 0x2f, 0xbf, 0xda, 0x80, + + /* U+0075 "u" */ + 0x2f, 0xe0, 0x0e, 0xbf, 0x52, 0xfe, 0x00, 0xeb, + 0xf5, 0x2f, 0xe0, 0x0e, 0xbf, 0x52, 0xfe, 0x00, + 0xeb, 0xf5, 0x2f, 0xe0, 0x0e, 0xbf, 0x52, 0xfe, + 0x00, 0xeb, 0xf5, 0x2f, 0xe0, 0x0e, 0xbf, 0x51, + 0xfe, 0x00, 0xeb, 0xf5, 0x1f, 0xf0, 0x06, 0x2f, + 0xf2, 0x87, 0x7a, 0x80, 0x0b, 0xbf, 0xca, 0x0f, + 0xfe, 0x9a, 0xfd, 0xaf, 0x50, 0x03, 0xef, 0xf4, + 0x04, 0x7a, 0x80, + + /* U+0076 "v" */ + 0x1f, 0xf2, 0x00, 0x70, 0xff, 0x88, 0x2b, 0xe8, + 0x03, 0x9b, 0xf0, 0x00, 0x9f, 0xe0, 0x0e, 0xcf, + 0x60, 0x0b, 0x7d, 0x40, 0x22, 0xff, 0x00, 0x68, + 0xfb, 0x00, 0xa3, 0xe4, 0x03, 0x0f, 0xf8, 0x40, + 0x1b, 0xe6, 0x01, 0xd7, 0xee, 0x07, 0xfa, 0x01, + 0xe5, 0xfd, 0x09, 0xf7, 0x00, 0xfb, 0xbc, 0xbb, + 0xc4, 0x03, 0xe9, 0xfc, 0xfa, 0x00, 0xfc, 0x7f, + 0xf2, 0x00, 0x7f, 0x6f, 0xf0, 0x07, 0x00, + + /* U+0077 "w" */ + 0x7f, 0x70, 0x0f, 0x93, 0xed, 0x7e, 0x40, 0x3e, + 0x6f, 0x93, 0xfb, 0x00, 0xfa, 0x3d, 0x87, 0xf4, + 0x00, 0xbe, 0xe0, 0x0a, 0xf4, 0x0e, 0xf0, 0x05, + 0x7e, 0x80, 0x2f, 0xc8, 0x33, 0xc4, 0x3b, 0xfc, + 0x41, 0xbe, 0x00, 0xaf, 0x34, 0xf9, 0xf8, 0x0f, + 0xd0, 0x04, 0x7a, 0xcf, 0x8f, 0x68, 0xfd, 0x80, + 0x17, 0xdf, 0xac, 0x27, 0xdb, 0xe0, 0x00, 0x7f, + 0x9e, 0xa0, 0x9f, 0xbe, 0xc0, 0x01, 0xff, 0x80, + 0x2e, 0xff, 0x20, 0x05, 0xdf, 0x60, 0x14, 0xff, + 0x88, 0x00, + + /* U+0078 "x" */ + 0x09, 0xfe, 0x10, 0x0d, 0x1f, 0xa0, 0x16, 0xfd, + 0x00, 0x47, 0xfe, 0x30, 0x08, 0xbf, 0xca, 0x00, + 0xdf, 0x70, 0x0e, 0x6f, 0xe1, 0x8f, 0xb0, 0x0f, + 0xaf, 0xf3, 0xf8, 0x40, 0x3e, 0x1e, 0xff, 0x20, + 0x07, 0xe1, 0xef, 0xf1, 0x80, 0x7e, 0xcf, 0xcf, + 0xe1, 0x00, 0xf4, 0x7e, 0x85, 0x7e, 0x00, 0x72, + 0x7f, 0x8c, 0x07, 0xbe, 0x00, 0x21, 0xef, 0x70, + 0x09, 0x3f, 0xca, 0x00, 0xcf, 0xc0, 0x0e, 0x9f, + 0xf1, 0x00, + + /* U+0079 "y" */ + 0x1f, 0xf2, 0x00, 0x70, 0xff, 0x88, 0x2b, 0xe8, + 0x03, 0x9b, 0xf0, 0x00, 0x9f, 0xe0, 0x0e, 0xcf, + 0x60, 0x0b, 0x7d, 0x80, 0x21, 0xff, 0x08, 0x04, + 0xff, 0x80, 0x13, 0xfd, 0x00, 0x61, 0xff, 0x10, + 0x03, 0x7d, 0x00, 0x3a, 0xfe, 0x00, 0xbf, 0x80, + 0x3c, 0x9f, 0xc1, 0x1f, 0x00, 0x1f, 0x77, 0x9e, + 0xf9, 0x00, 0x7d, 0x1f, 0x9f, 0x80, 0x1f, 0x8b, + 0xfe, 0x60, 0x0f, 0xec, 0xff, 0x00, 0x7f, 0xb3, + 0xe4, 0x03, 0xf9, 0x7f, 0xc2, 0x01, 0xf9, 0x3f, + 0xce, 0x01, 0xe4, 0xde, 0xff, 0x48, 0x07, 0xc9, + 0xfe, 0xb5, 0x00, 0xfc, + + /* U+007A "z" */ + 0x0e, 0xff, 0xfc, 0x00, 0xab, 0xbe, 0xdf, 0xf0, + 0x07, 0xc3, 0xde, 0xa0, 0x1f, 0x67, 0xc8, 0x07, + 0xd1, 0xf8, 0x01, 0xf2, 0x7f, 0x88, 0x03, 0xc3, + 0xde, 0xa0, 0x1f, 0x67, 0xc8, 0x07, 0xd1, 0xf8, + 0x01, 0xf2, 0x7f, 0x88, 0x03, 0xee, 0xfe, 0xbb, + 0xf2, 0x0f, 0xff, 0xf3, 0x00, + + /* U+007B "{" */ + 0x00, 0xe2, 0xae, 0xf8, 0x00, 0xc5, 0xdf, 0xd6, + 0xa0, 0x1a, 0x3e, 0x80, 0x3e, 0xbf, 0x30, 0x0f, + 0xb3, 0xc4, 0x03, 0xed, 0xf1, 0x00, 0xfb, 0x7c, + 0x40, 0x3e, 0xdf, 0x00, 0xf8, 0xff, 0x40, 0x3a, + 0xaf, 0xf8, 0xc0, 0x30, 0xff, 0xd0, 0x01, 0xf1, + 0x57, 0xd0, 0x07, 0xef, 0xf0, 0x07, 0xed, 0xf1, + 0x00, 0xfb, 0x7c, 0x80, 0x3e, 0xdf, 0x20, 0x0f, + 0xb7, 0xc8, 0x03, 0xec, 0xf2, 0x00, 0xfa, 0xfd, + 0x00, 0x3e, 0x8f, 0xb0, 0x0f, 0x87, 0xbf, 0xad, + 0x40, 0x38, 0xab, 0xbe, 0x00, + + /* U+007C "|" */ + 0x5f, 0x95, 0xf9, 0x5f, 0x95, 0xf9, 0x5f, 0x95, + 0xf9, 0x5f, 0x95, 0xf9, 0x5f, 0x95, 0xf9, 0x5f, + 0x95, 0xf9, 0x5f, 0x95, 0xf9, 0x5f, 0x95, 0xf9, + 0x5f, 0x95, 0xf9, 0x5f, 0x95, 0xf9, 0x5f, 0x95, + 0xf9, 0x5f, 0x95, 0xf9, + + /* U+007D "}" */ + 0x5f, 0xeb, 0x30, 0x0e, 0x3a, 0xdf, 0xf2, 0x00, + 0x7d, 0x1f, 0x60, 0x1f, 0xbf, 0xc0, 0x1f, 0xbb, + 0xc0, 0x3f, 0x77, 0x80, 0x7e, 0xef, 0x00, 0xfd, + 0xbe, 0x20, 0x1f, 0x57, 0xb8, 0x07, 0xc5, 0xbf, + 0x94, 0x60, 0x1c, 0xdd, 0xfe, 0x50, 0x0c, 0xdf, + 0x64, 0x01, 0xec, 0xf2, 0x00, 0xfb, 0xbc, 0x03, + 0xf7, 0x78, 0x07, 0xee, 0xf0, 0x0f, 0xdd, 0xe0, + 0x1f, 0xbb, 0xc0, 0x3f, 0x7f, 0x00, 0x7d, 0x1f, + 0x60, 0x18, 0xeb, 0x7f, 0xc6, 0x01, 0x97, 0xfa, + 0xcc, 0x03, 0x80, + + /* U+007E "~" */ + 0x00, 0x36, 0x61, 0xc0, 0x30, 0x90, 0x83, 0xff, + 0xec, 0x00, 0x9f, 0xd4, 0x3b, 0xc8, 0x99, 0xf8, + 0x21, 0x9e, 0x65, 0xf6, 0x01, 0x67, 0xfb, 0xbf, + 0x00, 0x54, 0xc0, 0x34, 0x77, 0xd0, 0x80, + + /* U+007F "" */ + + /* U+5010 "å€" */ + 0x00, 0xcd, 0x68, 0x01, 0xeb, 0x80, 0x0f, 0xfe, + 0x15, 0xf9, 0x80, 0x72, 0xfc, 0x00, 0x7f, 0xf0, + 0xbf, 0x80, 0x3d, 0xbf, 0x51, 0x1f, 0x00, 0x79, + 0x7e, 0x40, 0x40, 0x27, 0xff, 0xff, 0x00, 0x7a, + 0xbc, 0xcb, 0xe4, 0x0f, 0xfd, 0x40, 0x1d, 0x5f, + 0x20, 0x1e, 0xfd, 0x02, 0xf9, 0x1d, 0xfb, 0xf6, + 0x00, 0x9f, 0xec, 0x03, 0xcd, 0xfa, 0x05, 0xf3, + 0x9e, 0xc1, 0xbe, 0xe1, 0x3f, 0x82, 0x01, 0xed, + 0xfd, 0x02, 0xf9, 0x37, 0x00, 0x0e, 0xff, 0x7d, + 0x80, 0x7c, 0x9f, 0xed, 0x02, 0xf9, 0x00, 0xc3, + 0x3f, 0xf4, 0x08, 0x07, 0xb3, 0xfd, 0xa0, 0x5f, + 0x20, 0x02, 0x8f, 0xf7, 0x47, 0x7f, 0xa9, 0x88, + 0x00, 0x9f, 0x5d, 0xa0, 0x5f, 0x2f, 0xbf, 0xee, + 0x70, 0x09, 0xb7, 0xfe, 0xc0, 0xbf, 0x2e, 0xd0, + 0x2f, 0x97, 0xfb, 0x50, 0x03, 0xc0, 0x04, 0x4f, + 0x8c, 0x0f, 0x01, 0xda, 0x05, 0xf2, 0x02, 0x01, + 0xb7, 0xc0, 0x3f, 0x08, 0x03, 0xb4, 0x0b, 0xe4, + 0x1c, 0x80, 0x2e, 0xf0, 0x0d, 0x06, 0x01, 0xdd, + 0xa0, 0x5f, 0x27, 0xf8, 0x01, 0x7e, 0x80, 0x53, + 0xf8, 0x01, 0xdd, 0xa0, 0x5f, 0x21, 0x1e, 0xc0, + 0x3f, 0x60, 0x08, 0xfd, 0x10, 0x0e, 0xed, 0x02, + 0xf9, 0x00, 0x77, 0x01, 0x7f, 0xd0, 0x5f, 0xa2, + 0x01, 0xee, 0xd0, 0x2f, 0x90, 0x02, 0x10, 0x5f, + 0xf7, 0xda, 0x88, 0x07, 0xdd, 0xa0, 0x01, 0x00, + 0xe5, 0xfc, 0x1b, 0xfe, 0x30, 0x0f, 0xbb, 0x40, + 0x3e, 0x6f, 0xf1, 0x80, 0x23, 0xfc, 0xa0, 0x1e, + 0xed, 0x00, 0xe3, 0xbf, 0xf2, 0x00, 0x65, 0xff, + 0x40, 0x07, 0x76, 0x80, 0x4b, 0xbf, 0xec, 0x20, + 0x0f, 0x27, 0x7c, 0x80, 0x6e, 0xd0, 0x08, 0x7a, + 0xd4, 0x03, 0xf8, 0xb0, 0x80, 0x3f, 0xf9, 0xc0, + + /* U+5030 "倰" */ + 0x00, 0xe7, 0x40, 0x0f, 0xa9, 0xc0, 0x3f, 0xf8, + 0x03, 0xf6, 0x01, 0xe1, 0xfc, 0x00, 0xff, 0xe0, + 0x37, 0xb0, 0x07, 0x87, 0xf0, 0x03, 0xff, 0x81, + 0x7e, 0x31, 0xff, 0xff, 0xc2, 0x10, 0x0c, 0x5f, + 0x60, 0x91, 0x1d, 0x3f, 0xd1, 0x1e, 0x00, 0xe8, + 0xf5, 0x00, 0xf8, 0x7f, 0x00, 0x3f, 0xee, 0xf0, + 0x0f, 0xc3, 0xf8, 0x01, 0xfe, 0x7f, 0xe0, 0xbf, + 0xff, 0xfe, 0x21, 0x80, 0x3b, 0xf8, 0x1a, 0x23, + 0xff, 0x88, 0x21, 0x1f, 0xee, 0x00, 0xc5, 0x92, + 0x01, 0xcf, 0x88, 0x01, 0x8b, 0xfb, 0xa0, 0x09, + 0xff, 0xd2, 0x01, 0xcf, 0xdf, 0x88, 0x00, 0x9f, + 0x4d, 0xe0, 0x4d, 0xfe, 0x47, 0xb3, 0x00, 0xc3, + 0x1f, 0xec, 0x15, 0xa0, 0xde, 0x1e, 0xf8, 0x04, + 0xfd, 0x10, 0x0f, 0x15, 0x60, 0x00, 0x43, 0x78, + 0x0c, 0x80, 0xff, 0xff, 0xd6, 0x01, 0xed, 0xe0, + 0x08, 0xfb, 0xf6, 0x23, 0xd9, 0xf2, 0x01, 0xed, + 0xe0, 0x02, 0x7f, 0xb7, 0xd4, 0x03, 0x1f, 0xf0, + 0x80, 0x7b, 0x78, 0x1b, 0xfc, 0x83, 0xde, 0xa0, + 0x02, 0xef, 0x30, 0x0f, 0xb7, 0x82, 0xb8, 0xc0, + 0x05, 0xdf, 0x0b, 0xfe, 0x40, 0x0f, 0xdb, 0xc0, + 0x01, 0x00, 0xc3, 0xbf, 0xf1, 0x80, 0x7f, 0x6f, + 0x00, 0x78, 0xeb, 0xff, 0x5a, 0x00, 0x7e, 0xde, + 0x00, 0x8e, 0x37, 0xfd, 0x66, 0x6c, 0xff, 0x74, + 0x20, 0x07, 0x6f, 0x1d, 0xff, 0xdd, 0x24, 0x01, + 0x8e, 0xbf, 0xf2, 0x00, 0x5b, 0xc1, 0xdb, 0x28, + 0x01, 0xfc, 0x2d, 0x78, 0x01, 0xff, 0xcd +}; + + +static const sgl_font_table_t font_table[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 211, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 211, .box_w = 4, .box_h = 17, .ofs_x = 5, .ofs_y = 0}, + {.bitmap_index = 32, .adv_w = 211, .box_w = 8, .box_h = 6, .ofs_x = 3, .ofs_y = 11}, + {.bitmap_index = 57, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 139, .adv_w = 211, .box_w = 11, .box_h = 21, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 232, .adv_w = 211, .box_w = 13, .box_h = 17, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 332, .adv_w = 211, .box_w = 14, .box_h = 17, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 436, .adv_w = 211, .box_w = 3, .box_h = 6, .ofs_x = 5, .ofs_y = 11}, + {.bitmap_index = 445, .adv_w = 211, .box_w = 8, .box_h = 23, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 516, .adv_w = 211, .box_w = 7, .box_h = 23, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 583, .adv_w = 211, .box_w = 11, .box_h = 10, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 630, .adv_w = 211, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 677, .adv_w = 211, .box_w = 7, .box_h = 8, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 704, .adv_w = 211, .box_w = 8, .box_h = 2, .ofs_x = 3, .ofs_y = 5}, + {.bitmap_index = 710, .adv_w = 211, .box_w = 5, .box_h = 4, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 720, .adv_w = 211, .box_w = 13, .box_h = 17, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 783, .adv_w = 211, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 868, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 927, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 988, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1054, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1126, .adv_w = 211, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 1183, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1255, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1309, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1388, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1459, .adv_w = 211, .box_w = 5, .box_h = 12, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 1481, .adv_w = 211, .box_w = 7, .box_h = 16, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 1522, .adv_w = 211, .box_w = 10, .box_h = 14, .ofs_x = 1, .ofs_y = -1}, + {.bitmap_index = 1572, .adv_w = 211, .box_w = 11, .box_h = 6, .ofs_x = 1, .ofs_y = 4}, + {.bitmap_index = 1588, .adv_w = 211, .box_w = 10, .box_h = 14, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 1638, .adv_w = 211, .box_w = 8, .box_h = 17, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 1692, .adv_w = 211, .box_w = 14, .box_h = 22, .ofs_x = 0, .ofs_y = -5}, + {.bitmap_index = 1827, .adv_w = 211, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1906, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1980, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2044, .adv_w = 211, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2123, .adv_w = 211, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2173, .adv_w = 211, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2223, .adv_w = 211, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2300, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2366, .adv_w = 211, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2417, .adv_w = 211, .box_w = 9, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2469, .adv_w = 211, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2548, .adv_w = 211, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2597, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2687, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2767, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2850, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2916, .adv_w = 211, .box_w = 14, .box_h = 20, .ofs_x = 0, .ofs_y = -5}, + {.bitmap_index = 3026, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 3106, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3173, .adv_w = 211, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3227, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3299, .adv_w = 211, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3380, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3471, .adv_w = 211, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3551, .adv_w = 211, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3624, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3678, .adv_w = 211, .box_w = 6, .box_h = 22, .ofs_x = 4, .ofs_y = -5}, + {.bitmap_index = 3733, .adv_w = 211, .box_w = 11, .box_h = 19, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3796, .adv_w = 211, .box_w = 7, .box_h = 22, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 3860, .adv_w = 211, .box_w = 11, .box_h = 8, .ofs_x = 1, .ofs_y = 8}, + {.bitmap_index = 3897, .adv_w = 211, .box_w = 14, .box_h = 2, .ofs_x = 0, .ofs_y = -5}, + {.bitmap_index = 3905, .adv_w = 98, .box_w = 4, .box_h = 6, .ofs_x = 1, .ofs_y = 13}, + {.bitmap_index = 3918, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3978, .adv_w = 211, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4056, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4108, .adv_w = 211, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4186, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4240, .adv_w = 211, .box_w = 13, .box_h = 17, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4309, .adv_w = 211, .box_w = 12, .box_h = 17, .ofs_x = 1, .ofs_y = -5}, + {.bitmap_index = 4399, .adv_w = 211, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4474, .adv_w = 211, .box_w = 10, .box_h = 17, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 4531, .adv_w = 211, .box_w = 10, .box_h = 22, .ofs_x = 1, .ofs_y = -5}, + {.bitmap_index = 4608, .adv_w = 211, .box_w = 11, .box_h = 17, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 4686, .adv_w = 211, .box_w = 10, .box_h = 17, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 4745, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4821, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4879, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4944, .adv_w = 211, .box_w = 11, .box_h = 17, .ofs_x = 1, .ofs_y = -5}, + {.bitmap_index = 5021, .adv_w = 211, .box_w = 11, .box_h = 18, .ofs_x = 1, .ofs_y = -5}, + {.bitmap_index = 5101, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5152, .adv_w = 211, .box_w = 10, .box_h = 12, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5203, .adv_w = 211, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5266, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5325, .adv_w = 211, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5388, .adv_w = 211, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5462, .adv_w = 211, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5528, .adv_w = 211, .box_w = 13, .box_h = 17, .ofs_x = 0, .ofs_y = -5}, + {.bitmap_index = 5612, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5657, .adv_w = 211, .box_w = 10, .box_h = 22, .ofs_x = 1, .ofs_y = -5}, + {.bitmap_index = 5734, .adv_w = 211, .box_w = 3, .box_h = 24, .ofs_x = 5, .ofs_y = -5}, + {.bitmap_index = 5770, .adv_w = 211, .box_w = 10, .box_h = 22, .ofs_x = 2, .ofs_y = -5}, + {.bitmap_index = 5845, .adv_w = 211, .box_w = 13, .box_h = 5, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 5876, .adv_w = 211, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5876, .adv_w = 384, .box_w = 25, .box_h = 24, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 6116, .adv_w = 384, .box_w = 24, .box_h = 24, .ofs_x = 0, .ofs_y = -4} +}; + +static const uint32_t unicode_list_1[] = { + 0x00, 0x20 +}; + +static const sgl_font_unicode_t font_unicode[] = +{ + { .offset = 0x20, .len = 96, .list = NULL, .tab_offset = 1, }, + { .offset = 0x5010, .len = 2, .list = unicode_list_1, .tab_offset = 97, } +}; + +const sgl_font_t consolas24_compress = { + .bitmap = font_bitmap, + .table = font_table, + .font_table_size = SGL_ARRAY_SIZE(font_table), + .font_height = 25, + .base_line = 5, + .bpp = 4, + .compress = 1, + .unicode = font_unicode, + .unicode_num = 2, +}; + +#endif /* !CONFIG_SGL_FONT_CONSOLAS24_COMPRESS */ diff --git a/User/system/sgl/fonts/sgl_ascii_consolas34.c b/User/system/sgl/fonts/sgl_ascii_consolas34.c new file mode 100644 index 0000000..b524882 --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_consolas34.c @@ -0,0 +1,2048 @@ +/* source/fonts/sgl_ascii_consolas34.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + + +#if (CONFIG_SGL_FONT_CONSOLAS32) + + +static const uint8_t consolas32_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0x1f, 0xff, 0x11, 0xff, 0xf0, 0xf, 0xff, 0x0, + 0xff, 0xf0, 0xf, 0xff, 0x0, 0xff, 0xe0, 0xe, + 0xfe, 0x0, 0xef, 0xe0, 0xd, 0xfd, 0x0, 0xdf, + 0xd0, 0xc, 0xfc, 0x0, 0xcf, 0xc0, 0xb, 0xfb, + 0x0, 0xbf, 0xb0, 0xa, 0xfb, 0x0, 0x46, 0x40, + 0x0, 0x0, 0x0, 0x1, 0x0, 0xc, 0xfc, 0x6, + 0xff, 0xf5, 0x6f, 0xff, 0x50, 0xaf, 0xa0, + + /* U+0022 "\"" */ + 0x1f, 0xff, 0x30, 0x2f, 0xff, 0x10, 0xff, 0xf2, + 0x1, 0xff, 0xf0, 0xf, 0xff, 0x10, 0xf, 0xff, + 0x0, 0xef, 0xf0, 0x0, 0xff, 0xf0, 0xd, 0xff, + 0x0, 0xe, 0xfe, 0x0, 0xcf, 0xe0, 0x0, 0xef, + 0xd0, 0xb, 0xfe, 0x0, 0xd, 0xfc, 0x0, 0x35, + 0x40, 0x0, 0x45, 0x40, + + /* U+0023 "#" */ + 0x0, 0x0, 0xb, 0xf7, 0x0, 0xa, 0xf9, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0x50, 0x0, 0xcf, 0x70, + 0x0, 0x0, 0x0, 0xf, 0xf3, 0x0, 0xe, 0xf5, + 0x0, 0x0, 0x0, 0x2, 0xff, 0x10, 0x0, 0xff, + 0x30, 0x0, 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x60, 0x9f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf6, 0x0, 0x0, 0x7f, 0xc0, 0x0, + 0x5f, 0xe0, 0x0, 0x0, 0x0, 0x8, 0xfb, 0x0, + 0x6, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x9f, 0x90, + 0x0, 0x8f, 0xb0, 0x0, 0x0, 0x0, 0xb, 0xf8, + 0x0, 0x9, 0xfa, 0x0, 0x0, 0x0, 0x0, 0xcf, + 0x70, 0x0, 0xaf, 0x80, 0x0, 0x0, 0x0, 0xe, + 0xf5, 0x0, 0xc, 0xf7, 0x0, 0x0, 0x5f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x5, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, + 0x3, 0xff, 0x10, 0x1, 0xff, 0x30, 0x0, 0x0, + 0x0, 0x4f, 0xf0, 0x0, 0x2f, 0xf1, 0x0, 0x0, + 0x0, 0x5, 0xfe, 0x0, 0x4, 0xff, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x5f, 0xe0, 0x0, + 0x0, 0x0, 0x8, 0xfb, 0x0, 0x7, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0xaf, 0x90, 0x0, 0x8f, 0xb0, + 0x0, 0x0, + + /* U+0024 "$" */ + 0x0, 0x0, 0x0, 0x0, 0x88, 0x10, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x2f, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x4, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x5f, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0x7c, 0xef, 0xff, 0xdb, 0x70, 0x0, 0x4, 0xef, + 0xff, 0xff, 0xff, 0xfd, 0x0, 0x3, 0xff, 0xfa, + 0x6d, 0xfa, 0x7a, 0xb0, 0x0, 0xcf, 0xf4, 0x0, + 0xef, 0x50, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0xf, + 0xf2, 0x0, 0x0, 0x2, 0xff, 0xb0, 0x2, 0xff, + 0x0, 0x0, 0x0, 0xf, 0xff, 0x20, 0x4f, 0xe0, + 0x0, 0x0, 0x0, 0xaf, 0xfe, 0x56, 0xfc, 0x0, + 0x0, 0x0, 0x1, 0xdf, 0xff, 0xff, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0x8f, 0xff, 0xff, 0x92, 0x0, + 0x0, 0x0, 0x0, 0x29, 0xff, 0xff, 0xf9, 0x10, + 0x0, 0x0, 0x0, 0xe, 0xfe, 0xff, 0xfd, 0x10, + 0x0, 0x0, 0x0, 0xff, 0x25, 0xef, 0xfa, 0x0, + 0x0, 0x0, 0x2f, 0xf0, 0x2, 0xff, 0xf1, 0x0, + 0x0, 0x4, 0xfe, 0x0, 0xb, 0xff, 0x20, 0x0, + 0x0, 0x7f, 0xc0, 0x0, 0xcf, 0xf1, 0x0, 0x0, + 0x9, 0xfa, 0x0, 0x3f, 0xfc, 0x4, 0xc7, 0x53, + 0xbf, 0x93, 0x8f, 0xff, 0x40, 0x5f, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x40, 0x2, 0x9c, 0xef, 0xff, + 0xfe, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xfb, 0x0, 0x0, + 0x0, 0x0, + + /* U+0025 "%" */ + 0x0, 0x5d, 0xfe, 0x91, 0x0, 0x0, 0x2, 0xff, + 0x60, 0x6f, 0xfd, 0xff, 0xc0, 0x0, 0x0, 0xbf, + 0xc0, 0x1e, 0xf5, 0x1, 0xff, 0x50, 0x0, 0x5f, + 0xf2, 0x5, 0xfe, 0x0, 0xa, 0xf9, 0x0, 0x1e, + 0xf8, 0x0, 0x6f, 0xc0, 0x0, 0x9f, 0xa0, 0x9, + 0xfd, 0x0, 0x5, 0xfe, 0x0, 0xb, 0xf8, 0x4, + 0xff, 0x40, 0x0, 0x2f, 0xf7, 0x5, 0xff, 0x30, + 0xdf, 0x90, 0x0, 0x0, 0x9f, 0xff, 0xff, 0xa0, + 0x8f, 0xe1, 0x0, 0x0, 0x0, 0x7d, 0xfe, 0x70, + 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xaf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x5f, 0xf3, 0x7, 0xdf, 0xd8, 0x0, 0x0, + 0x0, 0xe, 0xf8, 0x9, 0xff, 0xff, 0xfa, 0x0, + 0x0, 0x9, 0xfd, 0x3, 0xff, 0x60, 0x6f, 0xf2, + 0x0, 0x3, 0xff, 0x40, 0x8f, 0xc0, 0x0, 0xdf, + 0x60, 0x0, 0xdf, 0xa0, 0x9, 0xf9, 0x0, 0xb, + 0xf7, 0x0, 0x7f, 0xe1, 0x0, 0x8f, 0xb0, 0x0, + 0xdf, 0x60, 0x2f, 0xf5, 0x0, 0x5, 0xff, 0x20, + 0x4f, 0xf1, 0xb, 0xfb, 0x0, 0x0, 0xc, 0xff, + 0xdf, 0xf7, 0x6, 0xff, 0x20, 0x0, 0x0, 0x9, + 0xef, 0xd6, 0x0, + + /* U+0026 "&" */ + 0x0, 0x0, 0x18, 0xdf, 0xfc, 0x50, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xdf, 0xff, 0xff, 0xf9, 0x0, + 0x0, 0x0, 0x0, 0xb, 0xff, 0xb6, 0x7e, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x2f, 0xfb, 0x0, 0x3, + 0xff, 0xa0, 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x0, + 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, 0x6f, 0xf5, + 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x4f, + 0xf8, 0x0, 0x4, 0xff, 0x80, 0x0, 0x0, 0x0, + 0xf, 0xfe, 0x10, 0x2e, 0xfe, 0x10, 0x0, 0x0, + 0x0, 0x9, 0xff, 0xa6, 0xff, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xef, 0xff, 0xfe, 0x30, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xb1, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1c, 0xff, 0xff, 0xd0, + 0x0, 0x1a, 0xa5, 0x0, 0x0, 0xdf, 0xf8, 0xcf, + 0xfa, 0x0, 0x3f, 0xf7, 0x0, 0x7, 0xff, 0x80, + 0x1e, 0xff, 0x70, 0x4f, 0xf5, 0x0, 0xe, 0xfe, + 0x0, 0x4, 0xff, 0xf3, 0x7f, 0xf3, 0x0, 0x1f, + 0xfb, 0x0, 0x0, 0x7f, 0xfe, 0xcf, 0xf0, 0x0, + 0x1f, 0xfa, 0x0, 0x0, 0xb, 0xff, 0xff, 0xa0, + 0x0, 0xf, 0xfd, 0x0, 0x0, 0x0, 0xdf, 0xff, + 0x30, 0x0, 0xc, 0xff, 0x50, 0x0, 0x0, 0x8f, + 0xff, 0x50, 0x0, 0x4, 0xff, 0xf8, 0x32, 0x4a, + 0xff, 0xff, 0xf2, 0x0, 0x0, 0x6f, 0xff, 0xff, + 0xff, 0xfc, 0xaf, 0xfd, 0x0, 0x0, 0x3, 0x9d, + 0xff, 0xda, 0x40, 0xc, 0xff, 0xa0, + + /* U+0027 "'" */ + 0x2f, 0xff, 0x31, 0xff, 0xf2, 0xf, 0xff, 0x10, + 0xff, 0xf0, 0xf, 0xff, 0x0, 0xef, 0xe0, 0xd, + 0xfe, 0x0, 0x45, 0x40, + + /* U+0028 "(" */ + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0x50, 0x0, 0x0, 0x3, 0xff, 0xd0, 0x0, + 0x0, 0x1e, 0xfe, 0x10, 0x0, 0x0, 0xbf, 0xf3, + 0x0, 0x0, 0x6, 0xff, 0x70, 0x0, 0x0, 0x1e, + 0xfd, 0x0, 0x0, 0x0, 0x8f, 0xf4, 0x0, 0x0, + 0x0, 0xff, 0xc0, 0x0, 0x0, 0x5, 0xff, 0x50, + 0x0, 0x0, 0xb, 0xff, 0x0, 0x0, 0x0, 0xf, + 0xfb, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, 0x0, + 0x0, 0x4f, 0xf5, 0x0, 0x0, 0x0, 0x6f, 0xf4, + 0x0, 0x0, 0x0, 0x7f, 0xf3, 0x0, 0x0, 0x0, + 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0xf5, 0x0, + 0x0, 0x0, 0x3f, 0xf7, 0x0, 0x0, 0x0, 0x1f, + 0xfb, 0x0, 0x0, 0x0, 0xc, 0xff, 0x0, 0x0, + 0x0, 0x8, 0xff, 0x40, 0x0, 0x0, 0x2, 0xff, + 0xb0, 0x0, 0x0, 0x0, 0xbf, 0xf2, 0x0, 0x0, + 0x0, 0x3f, 0xfb, 0x0, 0x0, 0x0, 0xa, 0xff, + 0x50, 0x0, 0x0, 0x1, 0xef, 0xe2, 0x0, 0x0, + 0x0, 0x4f, 0xfc, 0x0, 0x0, 0x0, 0x6, 0xff, + 0xb0, 0x0, 0x0, 0x0, 0x8f, 0x80, 0x0, 0x0, + 0x0, 0x5, 0x0, + + /* U+0029 ")" */ + 0x0, 0x10, 0x0, 0x0, 0x0, 0x4, 0xf5, 0x0, + 0x0, 0x0, 0xc, 0xff, 0x40, 0x0, 0x0, 0x2, + 0xef, 0xe2, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x70, 0x0, 0x0, 0x0, + 0xdf, 0xf1, 0x0, 0x0, 0x0, 0x4f, 0xf9, 0x0, + 0x0, 0x0, 0xc, 0xff, 0x10, 0x0, 0x0, 0x5, + 0xff, 0x70, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x8f, + 0xf3, 0x0, 0x0, 0x0, 0x5f, 0xf5, 0x0, 0x0, + 0x0, 0x4f, 0xf7, 0x0, 0x0, 0x0, 0x3f, 0xf7, + 0x0, 0x0, 0x0, 0x3f, 0xf7, 0x0, 0x0, 0x0, + 0x4f, 0xf6, 0x0, 0x0, 0x0, 0x7f, 0xf3, 0x0, + 0x0, 0x0, 0xaf, 0xf1, 0x0, 0x0, 0x0, 0xef, + 0xd0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0, + 0x9, 0xff, 0x20, 0x0, 0x0, 0x1f, 0xfa, 0x0, + 0x0, 0x0, 0x9f, 0xf3, 0x0, 0x0, 0x4, 0xff, + 0x90, 0x0, 0x0, 0x1e, 0xfe, 0x10, 0x0, 0x0, + 0xbf, 0xf3, 0x0, 0x0, 0xa, 0xff, 0x60, 0x0, + 0x0, 0x8, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x50, + 0x0, 0x0, 0x0, + + /* U+002A "*" */ + 0x0, 0x0, 0x8, 0xf9, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x7f, 0x80, 0x0, 0x0, 0x5, 0x0, 0x6, + 0xf6, 0x0, 0x5, 0x2, 0xfe, 0x40, 0x5f, 0x50, + 0x3d, 0xf2, 0x2c, 0xff, 0x84, 0xf5, 0x8f, 0xfd, + 0x30, 0x4, 0xcf, 0xef, 0xef, 0xd5, 0x0, 0x0, + 0x0, 0x6f, 0xff, 0x70, 0x0, 0x0, 0x1, 0x8f, + 0xff, 0xff, 0x81, 0x0, 0x18, 0xff, 0xc6, 0xf6, + 0xcf, 0xf8, 0x14, 0xff, 0x70, 0x5f, 0x50, 0x7f, + 0xf4, 0x8, 0x20, 0x6, 0xf6, 0x0, 0x28, 0x0, + 0x0, 0x0, 0x7f, 0x70, 0x0, 0x0, 0x0, 0x0, + 0x8, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, + 0x20, 0x0, 0x0, + + /* U+002B "+" */ + 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xc, 0xfd, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xcf, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xc, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xcf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc, 0xfd, 0x0, 0x0, 0x0, 0x46, 0x66, 0x66, + 0xdf, 0xe6, 0x66, 0x66, 0x4b, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0xbf, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xc, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x11, 0x0, 0x0, 0x0, + + /* U+002C "," */ + 0x0, 0x0, 0x56, 0x20, 0x0, 0x7, 0xff, 0xf2, + 0x0, 0xc, 0xff, 0xf9, 0x0, 0x9, 0xff, 0xfc, + 0x0, 0x1, 0xef, 0xfe, 0x0, 0x0, 0x8f, 0xfc, + 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x1, 0xdf, 0xf1, + 0x13, 0x7e, 0xff, 0x60, 0x6f, 0xff, 0xf6, 0x0, + 0x6e, 0xc8, 0x10, 0x0, + + /* U+002D "-" */ + 0x99, 0x99, 0x99, 0x99, 0x90, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf0, + + /* U+002E "." */ + 0x0, 0x2, 0x0, 0x4, 0xff, 0xd2, 0xe, 0xff, + 0xfa, 0x1f, 0xff, 0xfd, 0xd, 0xff, 0xf9, 0x2, + 0xcf, 0xa1, + + /* U+002F "/" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, + 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, + 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, + 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, + 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x8f, 0xe1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xaf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x9, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xa0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xe1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xb, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x6, 0xff, 0x20, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+0030 "0" */ + 0x0, 0x0, 0x3a, 0xdf, 0xeb, 0x60, 0x0, 0x0, + 0x0, 0x9f, 0xff, 0xff, 0xff, 0xc1, 0x0, 0x0, + 0x9f, 0xfe, 0x86, 0x8e, 0xff, 0xc0, 0x0, 0x3f, + 0xfc, 0x10, 0x0, 0x1c, 0xff, 0x60, 0xb, 0xff, + 0x20, 0x0, 0x0, 0x2f, 0xfd, 0x1, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0xbf, 0xf2, 0x5f, 0xf6, 0x0, + 0x0, 0x0, 0x9f, 0xff, 0x67, 0xff, 0x30, 0x0, + 0x1, 0xcf, 0xff, 0xf9, 0x9f, 0xf1, 0x0, 0x4, + 0xef, 0xf8, 0xff, 0xaa, 0xff, 0x0, 0x8, 0xff, + 0xd3, 0xf, 0xfb, 0xaf, 0xf0, 0x1b, 0xff, 0xa0, + 0x0, 0xff, 0xb9, 0xff, 0x3e, 0xff, 0x50, 0x0, + 0xf, 0xfa, 0x8f, 0xff, 0xfc, 0x20, 0x0, 0x2, + 0xff, 0x85, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x5f, + 0xf5, 0x2f, 0xfb, 0x0, 0x0, 0x0, 0x9, 0xff, + 0x10, 0xdf, 0xf2, 0x0, 0x0, 0x1, 0xff, 0xc0, + 0x6, 0xff, 0xc0, 0x0, 0x0, 0xcf, 0xf4, 0x0, + 0xc, 0xff, 0xe8, 0x57, 0xdf, 0xfa, 0x0, 0x0, + 0x1c, 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x0, + 0x6, 0xbe, 0xfe, 0xa4, 0x0, 0x0, + + /* U+0031 "1" */ + 0x0, 0x0, 0x18, 0xff, 0xa0, 0x0, 0x0, 0x0, + 0x7, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x7, 0xef, + 0xff, 0xff, 0xa0, 0x0, 0x0, 0xcf, 0xff, 0xa6, + 0xff, 0xa0, 0x0, 0x0, 0x7f, 0xc3, 0x4, 0xff, + 0xa0, 0x0, 0x0, 0x4, 0x0, 0x4, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0x4, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, + 0x4, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x4, + 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0x4, 0xff, 0xa0, 0x0, 0x0, 0x28, + 0x88, 0x8a, 0xff, 0xd8, 0x88, 0x80, 0x5f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf1, 0x5f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf1, + + /* U+0032 "2" */ + 0x0, 0x17, 0xce, 0xfe, 0xa3, 0x0, 0x0, 0x5, + 0xef, 0xff, 0xff, 0xff, 0x70, 0x0, 0x6f, 0xff, + 0xa7, 0x7c, 0xff, 0xf4, 0x0, 0x1e, 0xb1, 0x0, + 0x0, 0x8f, 0xfc, 0x0, 0x2, 0x0, 0x0, 0x0, + 0xe, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0xb, + 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, + 0x20, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf9, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0xf2, 0x0, 0x0, 0x0, + 0x0, 0xa, 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, + 0x9f, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0xa, 0xff, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0xaf, 0xf9, 0x0, 0x0, 0x0, 0x0, + 0xa, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x9f, + 0xff, 0x99, 0x99, 0x99, 0x99, 0x92, 0xcf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf4, 0xcf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf4, + + /* U+0033 "3" */ + 0x5, 0x9c, 0xef, 0xfd, 0x93, 0x0, 0x0, 0xff, + 0xff, 0xff, 0xff, 0xf9, 0x0, 0xe, 0xb8, 0x76, + 0x7b, 0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x0, 0x0, 0x0, + 0x2, 0x8f, 0xfa, 0x0, 0x0, 0x1f, 0xff, 0xff, + 0xf6, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xe7, + 0x0, 0x0, 0x4, 0x44, 0x69, 0xef, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xcf, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xff, 0xb0, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf8, + 0x0, 0x0, 0x0, 0x0, 0x3e, 0xff, 0x15, 0x97, + 0x65, 0x68, 0xcf, 0xff, 0x50, 0x8f, 0xff, 0xff, + 0xff, 0xfd, 0x40, 0x6, 0xde, 0xff, 0xed, 0xa5, + 0x0, 0x0, + + /* U+0034 "4" */ + 0x0, 0x0, 0x0, 0x0, 0x4f, 0xff, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x8d, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xd0, 0xdf, + 0xd0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf3, 0xd, + 0xfd, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, + 0xdf, 0xd0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, + 0xd, 0xfd, 0x0, 0x0, 0x0, 0x6, 0xff, 0x30, + 0x0, 0xdf, 0xd0, 0x0, 0x0, 0x1, 0xff, 0x90, + 0x0, 0xd, 0xfd, 0x0, 0x0, 0x0, 0xbf, 0xe0, + 0x0, 0x0, 0xdf, 0xd0, 0x0, 0x0, 0x6f, 0xf4, + 0x0, 0x0, 0xd, 0xfd, 0x0, 0x0, 0x1e, 0xf9, + 0x0, 0x0, 0x0, 0xdf, 0xd0, 0x0, 0x5, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x5f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x32, + 0x66, 0x66, 0x66, 0x66, 0x6e, 0xfe, 0x66, 0x61, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfd, + 0x0, 0x0, + + /* U+0035 "5" */ + 0xf, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xb0, 0xf, 0xfb, 0x66, + 0x66, 0x66, 0x64, 0x0, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb5, + 0x54, 0x20, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, + 0xe9, 0x20, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x25, 0xcf, 0xfe, 0x10, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf7, 0x0, 0x0, + 0x0, 0x0, 0x3, 0xff, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x3, + 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfc, 0x3, 0x97, + 0x65, 0x68, 0xdf, 0xfe, 0x20, 0x5f, 0xff, 0xff, + 0xff, 0xfb, 0x10, 0x3, 0xdf, 0xff, 0xec, 0x93, + 0x0, 0x0, + + /* U+0036 "6" */ + 0x0, 0x0, 0x0, 0x39, 0xce, 0xff, 0xf0, 0x0, + 0x0, 0x3, 0xcf, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x5, 0xff, 0xfe, 0xa7, 0x66, 0x50, 0x0, 0x2, + 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, + 0xd1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xa2, 0x8c, + 0xef, 0xeb, 0x50, 0x0, 0xf, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xa0, 0x0, 0xff, 0xff, 0xb6, 0x44, + 0x7f, 0xff, 0x80, 0x1f, 0xfc, 0x20, 0x0, 0x0, + 0x2f, 0xff, 0x12, 0xff, 0x90, 0x0, 0x0, 0x0, + 0x9f, 0xf5, 0x1f, 0xfa, 0x0, 0x0, 0x0, 0x5, + 0xff, 0x70, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x4f, + 0xf7, 0xd, 0xff, 0x0, 0x0, 0x0, 0x6, 0xff, + 0x50, 0x9f, 0xf4, 0x0, 0x0, 0x0, 0xbf, 0xf1, + 0x3, 0xff, 0xd0, 0x0, 0x0, 0x5f, 0xfa, 0x0, + 0xa, 0xff, 0xd6, 0x44, 0x9f, 0xfe, 0x10, 0x0, + 0xb, 0xff, 0xff, 0xff, 0xfd, 0x20, 0x0, 0x0, + 0x5, 0xbe, 0xfe, 0xb6, 0x0, 0x0, + + /* U+0037 "7" */ + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x23, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x28, + 0x88, 0x88, 0x88, 0x88, 0x8d, 0xff, 0x10, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x8f, 0xf3, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x8, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, + 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf6, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x7, 0xff, 0x70, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xf1, 0x0, 0x0, 0x0, 0x0, + + /* U+0038 "8" */ + 0x0, 0x0, 0x7c, 0xef, 0xfd, 0x93, 0x0, 0x0, + 0x3, 0xef, 0xff, 0xff, 0xff, 0xf7, 0x0, 0x1, + 0xef, 0xfa, 0x64, 0x6a, 0xff, 0xf4, 0x0, 0x8f, + 0xf6, 0x0, 0x0, 0x5, 0xff, 0xa0, 0xb, 0xff, + 0x0, 0x0, 0x0, 0xf, 0xfc, 0x0, 0xbf, 0xf1, + 0x0, 0x0, 0x0, 0xff, 0xa0, 0x7, 0xff, 0xa0, + 0x0, 0x0, 0x8f, 0xf6, 0x0, 0xe, 0xff, 0xc2, + 0x0, 0x9f, 0xfc, 0x0, 0x0, 0x2d, 0xff, 0xfb, + 0xef, 0xfb, 0x0, 0x0, 0x0, 0x9, 0xff, 0xff, + 0xf8, 0x0, 0x0, 0x0, 0x6, 0xef, 0xff, 0xff, + 0xf9, 0x0, 0x0, 0x9, 0xff, 0xd4, 0x7, 0xff, + 0xfc, 0x0, 0x6, 0xff, 0xb0, 0x0, 0x1, 0xcf, + 0xf9, 0x0, 0xef, 0xf1, 0x0, 0x0, 0x1, 0xef, + 0xf1, 0x2f, 0xfb, 0x0, 0x0, 0x0, 0xb, 0xff, + 0x32, 0xff, 0xb0, 0x0, 0x0, 0x0, 0xbf, 0xf3, + 0xf, 0xff, 0x50, 0x0, 0x0, 0x4f, 0xfe, 0x0, + 0x8f, 0xff, 0xb7, 0x56, 0xaf, 0xff, 0x70, 0x0, + 0xaf, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, 0x0, + 0x39, 0xdf, 0xfe, 0xc8, 0x20, 0x0, + + /* U+0039 "9" */ + 0x0, 0x0, 0x7c, 0xef, 0xea, 0x40, 0x0, 0x0, + 0x3, 0xef, 0xff, 0xff, 0xff, 0x90, 0x0, 0x2, + 0xff, 0xfa, 0x54, 0x6d, 0xff, 0x80, 0x0, 0xcf, + 0xf5, 0x0, 0x0, 0xc, 0xff, 0x10, 0x2f, 0xfa, + 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x6, 0xff, 0x50, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x7f, 0xf5, 0x0, + 0x0, 0x0, 0xb, 0xff, 0x6, 0xff, 0x70, 0x0, + 0x0, 0x0, 0xaf, 0xf1, 0x2f, 0xfd, 0x0, 0x0, + 0x0, 0xa, 0xff, 0x20, 0xbf, 0xfc, 0x30, 0x2, + 0x6c, 0xff, 0xf1, 0x1, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0, 0x1, 0x9e, 0xff, 0xff, 0xc6, + 0xaf, 0xf0, 0x0, 0x0, 0x1, 0x22, 0x0, 0xc, + 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x20, 0x0, + 0x16, 0x66, 0x8b, 0xff, 0xfe, 0x40, 0x0, 0x4, + 0xff, 0xff, 0xff, 0xfb, 0x20, 0x0, 0x0, 0x4f, + 0xfe, 0xdb, 0x72, 0x0, 0x0, 0x0, + + /* U+003A ":" */ + 0x1a, 0xfb, 0x19, 0xff, 0xf9, 0xcf, 0xff, 0xc7, + 0xff, 0xf8, 0x8, 0xc8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7c, 0x80, 0x7f, 0xff, + 0x8b, 0xff, 0xfc, 0x9f, 0xff, 0x91, 0xbf, 0xb1, + + /* U+003B ";" */ + 0x0, 0x1, 0xaf, 0xb1, 0x0, 0x0, 0x9f, 0xff, + 0x90, 0x0, 0xc, 0xff, 0xfc, 0x0, 0x0, 0x7f, + 0xff, 0x80, 0x0, 0x0, 0x8c, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0x0, 0x0, 0x0, 0x2e, 0xfc, 0x10, 0x0, 0x9, + 0xff, 0xfa, 0x0, 0x0, 0x8f, 0xff, 0xf0, 0x0, + 0x1, 0xef, 0xff, 0x0, 0x0, 0x6, 0xff, 0xf0, + 0x0, 0x0, 0x4f, 0xfc, 0x0, 0x0, 0x9, 0xff, + 0x60, 0x1, 0x4b, 0xff, 0xc0, 0x3, 0xff, 0xff, + 0xb1, 0x0, 0x3f, 0xfb, 0x50, 0x0, 0x0, 0x10, + 0x0, 0x0, 0x0, + + /* U+003C "<" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, + 0x0, 0x0, 0xa, 0xe2, 0x0, 0x0, 0x0, 0x1, + 0xcf, 0xf9, 0x0, 0x0, 0x0, 0x2d, 0xff, 0x90, + 0x0, 0x0, 0x3, 0xef, 0xf7, 0x0, 0x0, 0x0, + 0x5f, 0xff, 0x40, 0x0, 0x0, 0x7, 0xff, 0xe3, + 0x0, 0x0, 0x0, 0x9f, 0xfc, 0x10, 0x0, 0x0, + 0xb, 0xff, 0xb0, 0x0, 0x0, 0x0, 0xaf, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xc1, 0x0, + 0x0, 0x0, 0x0, 0x8f, 0xfd, 0x20, 0x0, 0x0, + 0x0, 0x6, 0xff, 0xe4, 0x0, 0x0, 0x0, 0x0, + 0x4f, 0xff, 0x60, 0x0, 0x0, 0x0, 0x3, 0xef, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x1d, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf9, 0x0, 0x0, + 0x0, 0x0, 0x9, 0xd1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x10, + + /* U+003D "=" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x45, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x50, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + + /* U+003E ">" */ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xfc, 0x10, 0x0, + 0x0, 0x0, 0x9, 0xff, 0xe2, 0x0, 0x0, 0x0, + 0x0, 0x6f, 0xff, 0x40, 0x0, 0x0, 0x0, 0x4, + 0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x3e, 0xff, + 0x80, 0x0, 0x0, 0x0, 0x1, 0xdf, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0xb, 0xff, 0xc1, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xfa, 0x0, 0x0, 0x0, 0xb, + 0xff, 0xb0, 0x0, 0x0, 0x1, 0xdf, 0xf9, 0x0, + 0x0, 0x0, 0x3e, 0xff, 0x70, 0x0, 0x0, 0x5, + 0xff, 0xf5, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x30, + 0x0, 0x0, 0x9, 0xff, 0xd2, 0x0, 0x0, 0x0, + 0x9f, 0xfc, 0x10, 0x0, 0x0, 0x0, 0x1d, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, + 0x0, 0x0, + + /* U+003F "?" */ + 0x6f, 0xeb, 0x72, 0x0, 0x0, 0x6f, 0xff, 0xff, + 0xa1, 0x0, 0x27, 0x9c, 0xff, 0xfd, 0x10, 0x0, + 0x0, 0x2c, 0xff, 0xc0, 0x0, 0x0, 0x0, 0xcf, + 0xf6, 0x0, 0x0, 0x0, 0x3f, 0xfb, 0x0, 0x0, + 0x0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0xf, 0xfe, + 0x0, 0x0, 0x0, 0x3f, 0xfc, 0x0, 0x11, 0x15, + 0xef, 0xf6, 0x0, 0xef, 0xff, 0xff, 0xb0, 0x0, + 0xef, 0xff, 0xc6, 0x0, 0x0, 0xdf, 0x90, 0x0, + 0x0, 0x0, 0xdf, 0x90, 0x0, 0x0, 0x0, 0xcf, + 0x80, 0x0, 0x0, 0x0, 0x9c, 0x60, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, + 0x0, 0x0, 0x1, 0xdf, 0xa0, 0x0, 0x0, 0x8, + 0xff, 0xf4, 0x0, 0x0, 0x7, 0xff, 0xf3, 0x0, + 0x0, 0x1, 0xbf, 0x90, 0x0, 0x0, + + /* U+0040 "@" */ + 0x0, 0x0, 0x0, 0x18, 0xdf, 0xec, 0x70, 0x0, + 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0xff, 0xd2, + 0x0, 0x0, 0x0, 0x7f, 0xf9, 0x20, 0x4, 0xdf, + 0xd0, 0x0, 0x0, 0x5f, 0xf6, 0x0, 0x0, 0x1, + 0xef, 0x70, 0x0, 0x1e, 0xf8, 0x0, 0x0, 0x0, + 0x5, 0xfe, 0x0, 0x8, 0xfd, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xf3, 0x0, 0xff, 0x50, 0x0, 0x0, + 0x0, 0x0, 0xbf, 0x70, 0x6f, 0xd0, 0x0, 0x8e, + 0xfc, 0xad, 0x8, 0xf9, 0xb, 0xf8, 0x0, 0xbf, + 0xff, 0xff, 0xc0, 0x6f, 0xb0, 0xff, 0x30, 0x6f, + 0xf4, 0x1d, 0xf9, 0x5, 0xfc, 0x4f, 0xf0, 0xd, + 0xf9, 0x0, 0xef, 0x70, 0x4f, 0xd7, 0xfc, 0x2, + 0xff, 0x30, 0xf, 0xf5, 0x5, 0xfc, 0x9f, 0x90, + 0x6f, 0xf0, 0x3, 0xff, 0x20, 0x5f, 0xbb, 0xf7, + 0x9, 0xfc, 0x0, 0x5f, 0xf0, 0x7, 0xfa, 0xcf, + 0x50, 0xbf, 0xb0, 0x8, 0xfd, 0x0, 0x9f, 0x8d, + 0xf5, 0xb, 0xfa, 0x0, 0xaf, 0xb0, 0xc, 0xf5, + 0xdf, 0x40, 0xbf, 0xb0, 0x1e, 0xfa, 0x1, 0xff, + 0x1c, 0xf5, 0x9, 0xfe, 0x1a, 0xff, 0xd1, 0x9f, + 0xb0, 0xbf, 0x60, 0x4f, 0xff, 0xf7, 0xef, 0xff, + 0xf2, 0xa, 0xf8, 0x0, 0x7f, 0xf9, 0x5, 0xef, + 0xc3, 0x0, 0x8f, 0xa0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x5, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf3, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0x60, 0x0, + 0x0, 0x0, 0x10, 0x0, 0x0, 0xa, 0xff, 0x92, + 0x0, 0x14, 0xad, 0x0, 0x0, 0x0, 0xa, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x4, + 0xae, 0xff, 0xda, 0x50, 0x0, 0x0, + + /* U+0041 "A" */ + 0x0, 0x0, 0x0, 0x7f, 0xff, 0x90, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xc, 0xff, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0xff, 0xef, 0xf3, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf5, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0xe, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x9f, + 0xf3, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf2, 0x4, + 0xff, 0x80, 0x0, 0x0, 0x0, 0xb, 0xfd, 0x0, + 0xe, 0xfd, 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, + 0x0, 0x9f, 0xf2, 0x0, 0x0, 0x0, 0x6f, 0xf3, + 0x0, 0x4, 0xff, 0x70, 0x0, 0x0, 0xb, 0xfe, + 0x0, 0x0, 0xf, 0xfd, 0x0, 0x0, 0x1, 0xff, + 0x90, 0x0, 0x0, 0xaf, 0xf2, 0x0, 0x0, 0x6f, + 0xf4, 0x0, 0x0, 0x5, 0xff, 0x70, 0x0, 0xb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x1, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x0, + 0x5f, 0xf9, 0x77, 0x77, 0x77, 0x7a, 0xff, 0x60, + 0xb, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, + 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xcf, + 0xf1, 0x5f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x8, + 0xff, 0x6a, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xfb, + + /* U+0042 "B" */ + 0x9f, 0xff, 0xff, 0xfe, 0xc8, 0x20, 0x0, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xf6, 0x0, 0x9f, 0xf6, + 0x55, 0x68, 0xdf, 0xff, 0x20, 0x9f, 0xf1, 0x0, + 0x0, 0xa, 0xff, 0x80, 0x9f, 0xf1, 0x0, 0x0, + 0x3, 0xff, 0xa0, 0x9f, 0xf1, 0x0, 0x0, 0x3, + 0xff, 0x80, 0x9f, 0xf1, 0x0, 0x0, 0x9, 0xff, + 0x30, 0x9f, 0xf1, 0x0, 0x13, 0xaf, 0xf9, 0x0, + 0x9f, 0xff, 0xff, 0xff, 0xfd, 0x50, 0x0, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x0, 0x9f, 0xf6, + 0x55, 0x68, 0xdf, 0xff, 0x30, 0x9f, 0xf1, 0x0, + 0x0, 0x8, 0xff, 0xd0, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0xcf, 0xf3, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x8f, 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x8f, + 0xf4, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xcf, 0xf1, + 0x9f, 0xf1, 0x0, 0x0, 0x7, 0xff, 0xb0, 0x9f, + 0xf6, 0x55, 0x57, 0xcf, 0xfe, 0x20, 0x9f, 0xff, + 0xff, 0xff, 0xff, 0xd2, 0x0, 0x9f, 0xff, 0xff, + 0xfd, 0xa5, 0x0, 0x0, + + /* U+0043 "C" */ + 0x0, 0x0, 0x3, 0x8d, 0xef, 0xdc, 0x93, 0x0, + 0x0, 0x1a, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x0, + 0x1d, 0xff, 0xfc, 0x98, 0x8b, 0xff, 0x10, 0xb, + 0xff, 0xc2, 0x0, 0x0, 0x0, 0x60, 0x5, 0xff, + 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x5, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x9, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x9f, 0xf4, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x8, 0xff, 0x50, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf7, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x4, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x9f, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0xff, 0xfb, 0x10, 0x0, 0x0, 0x5, 0x0, + 0x5, 0xff, 0xff, 0xb8, 0x88, 0xbf, 0xf1, 0x0, + 0x4, 0xef, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, + 0x0, 0x6a, 0xef, 0xfe, 0xc8, 0x30, + + /* U+0044 "D" */ + 0x5f, 0xff, 0xff, 0xfe, 0xb7, 0x10, 0x0, 0x5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x5f, + 0xf9, 0x55, 0x68, 0xcf, 0xff, 0xa0, 0x5, 0xff, + 0x50, 0x0, 0x0, 0x4e, 0xff, 0x60, 0x5f, 0xf5, + 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x5, 0xff, 0x50, + 0x0, 0x0, 0x0, 0xaf, 0xf5, 0x5f, 0xf5, 0x0, + 0x0, 0x0, 0x4, 0xff, 0x95, 0xff, 0x50, 0x0, + 0x0, 0x0, 0x1f, 0xfc, 0x5f, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xd5, 0xff, 0x50, 0x0, 0x0, + 0x0, 0xe, 0xfe, 0x5f, 0xf5, 0x0, 0x0, 0x0, + 0x0, 0xef, 0xe5, 0xff, 0x50, 0x0, 0x0, 0x0, + 0xf, 0xfc, 0x5f, 0xf5, 0x0, 0x0, 0x0, 0x2, + 0xff, 0xb5, 0xff, 0x50, 0x0, 0x0, 0x0, 0x6f, + 0xf7, 0x5f, 0xf5, 0x0, 0x0, 0x0, 0xc, 0xff, + 0x25, 0xff, 0x50, 0x0, 0x0, 0x7, 0xff, 0xb0, + 0x5f, 0xf5, 0x0, 0x0, 0x8, 0xff, 0xf2, 0x5, + 0xff, 0x96, 0x67, 0xae, 0xff, 0xf5, 0x0, 0x5f, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x0, 0x5, 0xff, + 0xff, 0xfe, 0xc9, 0x30, 0x0, 0x0, + + /* U+0045 "E" */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf4, 0xff, 0xd5, 0x55, 0x55, + 0x55, 0x51, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0xff, 0xd5, 0x55, 0x55, + 0x55, 0x50, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xd6, + 0x66, 0x66, 0x66, 0x61, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, + + /* U+0046 "F" */ + 0xef, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xf4, 0xef, 0xe6, 0x66, 0x66, + 0x66, 0x61, 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xe5, 0x55, 0x55, 0x55, 0x40, 0xef, 0xff, + 0xff, 0xff, 0xff, 0xd0, 0xef, 0xff, 0xff, 0xff, + 0xff, 0xd0, 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0xd0, 0x0, 0x0, 0x0, 0x0, + + /* U+0047 "G" */ + 0x0, 0x0, 0x3, 0x9d, 0xef, 0xec, 0x94, 0x0, + 0x0, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x0, + 0x3e, 0xff, 0xfc, 0x98, 0x9b, 0xff, 0x30, 0x1e, + 0xff, 0xb2, 0x0, 0x0, 0x0, 0x41, 0xa, 0xff, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf7, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x20, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xe0, 0x0, 0x6, + 0xff, 0xff, 0xff, 0x5f, 0xfd, 0x0, 0x0, 0x6f, + 0xff, 0xff, 0xf5, 0xff, 0xd0, 0x0, 0x1, 0x44, + 0x48, 0xff, 0x5e, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x5f, 0xf5, 0xdf, 0xf0, 0x0, 0x0, 0x0, 0x5, + 0xff, 0x59, 0xff, 0x40, 0x0, 0x0, 0x0, 0x5f, + 0xf5, 0x5f, 0xfb, 0x0, 0x0, 0x0, 0x5, 0xff, + 0x50, 0xef, 0xf5, 0x0, 0x0, 0x0, 0x5f, 0xf5, + 0x6, 0xff, 0xf7, 0x0, 0x0, 0x5, 0xff, 0x50, + 0x9, 0xff, 0xfe, 0xa8, 0x79, 0xdf, 0xf5, 0x0, + 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x0, + 0x1, 0x7b, 0xef, 0xfd, 0xb7, 0x10, + + /* U+0048 "H" */ + 0x5f, 0xf6, 0x0, 0x0, 0x0, 0x5, 0xff, 0x65, + 0xff, 0x60, 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x5f, + 0xf6, 0x0, 0x0, 0x0, 0x5, 0xff, 0x65, 0xff, + 0x60, 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x5f, 0xf6, + 0x0, 0x0, 0x0, 0x5, 0xff, 0x65, 0xff, 0x60, + 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x5f, 0xf6, 0x0, + 0x0, 0x0, 0x5, 0xff, 0x65, 0xff, 0x60, 0x0, + 0x0, 0x0, 0x5f, 0xf6, 0x5f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x65, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf6, 0x5f, 0xfa, 0x66, 0x66, 0x66, + 0x69, 0xff, 0x65, 0xff, 0x60, 0x0, 0x0, 0x0, + 0x5f, 0xf6, 0x5f, 0xf6, 0x0, 0x0, 0x0, 0x5, + 0xff, 0x65, 0xff, 0x60, 0x0, 0x0, 0x0, 0x5f, + 0xf6, 0x5f, 0xf6, 0x0, 0x0, 0x0, 0x5, 0xff, + 0x65, 0xff, 0x60, 0x0, 0x0, 0x0, 0x5f, 0xf6, + 0x5f, 0xf6, 0x0, 0x0, 0x0, 0x5, 0xff, 0x65, + 0xff, 0x60, 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x5f, + 0xf6, 0x0, 0x0, 0x0, 0x5, 0xff, 0x65, 0xff, + 0x60, 0x0, 0x0, 0x0, 0x5f, 0xf6, + + /* U+0049 "I" */ + 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf7, 0x25, 0x55, 0x5e, + 0xfe, 0x55, 0x55, 0x20, 0x0, 0x0, 0xdf, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x2, 0x66, + 0x66, 0xef, 0xe6, 0x66, 0x62, 0x6f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x76, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf7, + + /* U+004A "J" */ + 0xf, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf, 0xff, + 0xff, 0xff, 0xff, 0xf4, 0x6, 0x66, 0x66, 0x66, + 0xbf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x9f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xf1, + 0x36, 0x0, 0x0, 0x6, 0xff, 0xb0, 0x4f, 0xea, + 0x77, 0xbf, 0xff, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xf5, 0x0, 0x3, 0x9d, 0xff, 0xd9, 0x20, 0x0, + + /* U+004B "K" */ + 0xaf, 0xf1, 0x0, 0x0, 0x2, 0xff, 0xe2, 0xaf, + 0xf1, 0x0, 0x0, 0xd, 0xff, 0x40, 0xaf, 0xf1, + 0x0, 0x0, 0xaf, 0xf7, 0x0, 0xaf, 0xf1, 0x0, + 0x6, 0xff, 0x90, 0x0, 0xaf, 0xf1, 0x0, 0x3f, + 0xfc, 0x0, 0x0, 0xaf, 0xf1, 0x1, 0xef, 0xe1, + 0x0, 0x0, 0xaf, 0xf1, 0xb, 0xff, 0x30, 0x0, + 0x0, 0xaf, 0xf1, 0x8f, 0xf5, 0x0, 0x0, 0x0, + 0xaf, 0xf6, 0xff, 0x80, 0x0, 0x0, 0x0, 0xaf, + 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xfc, + 0xff, 0x70, 0x0, 0x0, 0x0, 0xaf, 0xf2, 0xef, + 0xf4, 0x0, 0x0, 0x0, 0xaf, 0xf1, 0x3f, 0xfe, + 0x10, 0x0, 0x0, 0xaf, 0xf1, 0x7, 0xff, 0xc0, + 0x0, 0x0, 0xaf, 0xf1, 0x0, 0xbf, 0xf9, 0x0, + 0x0, 0xaf, 0xf1, 0x0, 0x1d, 0xff, 0x50, 0x0, + 0xaf, 0xf1, 0x0, 0x3, 0xff, 0xf2, 0x0, 0xaf, + 0xf1, 0x0, 0x0, 0x6f, 0xfd, 0x0, 0xaf, 0xf1, + 0x0, 0x0, 0xa, 0xff, 0xa0, 0xaf, 0xf1, 0x0, + 0x0, 0x0, 0xdf, 0xf7, + + /* U+004C "L" */ + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf8, + 0x66, 0x66, 0x66, 0x65, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, + + /* U+004D "M" */ + 0x5, 0xff, 0xf1, 0x0, 0x0, 0x2, 0xff, 0xf5, + 0x0, 0x5f, 0xff, 0x60, 0x0, 0x0, 0x7f, 0xff, + 0x60, 0x6, 0xff, 0xfc, 0x0, 0x0, 0xd, 0xff, + 0xf7, 0x0, 0x7f, 0xcf, 0xf2, 0x0, 0x3, 0xfd, + 0xdf, 0x80, 0x8, 0xfa, 0xcf, 0x70, 0x0, 0x9f, + 0x8d, 0xf8, 0x0, 0x9f, 0xa7, 0xfd, 0x0, 0xf, + 0xf2, 0xcf, 0x90, 0x9, 0xfa, 0x2f, 0xf3, 0x5, + 0xfd, 0xc, 0xfa, 0x0, 0xaf, 0xa0, 0xcf, 0x80, + 0xbf, 0x70, 0xbf, 0xb0, 0xb, 0xf9, 0x6, 0xfe, + 0x1f, 0xf1, 0xb, 0xfb, 0x0, 0xcf, 0x90, 0x1f, + 0xf9, 0xfb, 0x0, 0xaf, 0xc0, 0xc, 0xf8, 0x0, + 0xaf, 0xff, 0x50, 0xa, 0xfd, 0x0, 0xdf, 0x80, + 0x5, 0xff, 0xf0, 0x0, 0x9f, 0xe0, 0xe, 0xf8, + 0x0, 0xe, 0xfa, 0x0, 0x9, 0xff, 0x0, 0xff, + 0x70, 0x0, 0x57, 0x20, 0x0, 0x8f, 0xf0, 0xf, + 0xf7, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0x0, + 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf1, + 0x1f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x22, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x6f, + 0xf2, 0x3f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0x33, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x5f, 0xf4, + + /* U+004E "N" */ + 0x3f, 0xff, 0x70, 0x0, 0x0, 0x4, 0xff, 0x43, + 0xff, 0xfe, 0x0, 0x0, 0x0, 0x4f, 0xf4, 0x3f, + 0xff, 0xf6, 0x0, 0x0, 0x4, 0xff, 0x43, 0xff, + 0xff, 0xe0, 0x0, 0x0, 0x4f, 0xf4, 0x3f, 0xf9, + 0xff, 0x50, 0x0, 0x4, 0xff, 0x43, 0xff, 0x5d, + 0xfd, 0x0, 0x0, 0x4f, 0xf4, 0x3f, 0xf5, 0x7f, + 0xf4, 0x0, 0x4, 0xff, 0x43, 0xff, 0x51, 0xff, + 0xc0, 0x0, 0x4f, 0xf4, 0x3f, 0xf5, 0x9, 0xff, + 0x30, 0x4, 0xff, 0x43, 0xff, 0x50, 0x1f, 0xfa, + 0x0, 0x4f, 0xf4, 0x3f, 0xf5, 0x0, 0xaf, 0xf2, + 0x4, 0xff, 0x43, 0xff, 0x50, 0x2, 0xff, 0x90, + 0x4f, 0xf4, 0x3f, 0xf5, 0x0, 0xb, 0xff, 0x14, + 0xff, 0x43, 0xff, 0x50, 0x0, 0x4f, 0xf7, 0x4f, + 0xf4, 0x3f, 0xf5, 0x0, 0x0, 0xcf, 0xe4, 0xff, + 0x43, 0xff, 0x50, 0x0, 0x5, 0xff, 0x9f, 0xf4, + 0x3f, 0xf5, 0x0, 0x0, 0xd, 0xff, 0xff, 0x43, + 0xff, 0x50, 0x0, 0x0, 0x6f, 0xff, 0xf4, 0x3f, + 0xf5, 0x0, 0x0, 0x0, 0xef, 0xff, 0x43, 0xff, + 0x50, 0x0, 0x0, 0x7, 0xff, 0xf4, + + /* U+004F "O" */ + 0x0, 0x0, 0x4, 0xae, 0xfe, 0xc7, 0x10, 0x0, + 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xfe, 0x40, + 0x0, 0x0, 0xc, 0xff, 0xe9, 0x79, 0xef, 0xff, + 0x30, 0x0, 0x8, 0xff, 0xb1, 0x0, 0x0, 0x9f, + 0xfd, 0x0, 0x1, 0xff, 0xe1, 0x0, 0x0, 0x0, + 0xcf, 0xf5, 0x0, 0x7f, 0xf6, 0x0, 0x0, 0x0, + 0x4, 0xff, 0xa0, 0xb, 0xff, 0x10, 0x0, 0x0, + 0x0, 0xf, 0xfe, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0xcf, 0xf0, 0xf, 0xfb, 0x0, 0x0, + 0x0, 0x0, 0xa, 0xff, 0x21, 0xff, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0x9f, 0xf3, 0x1f, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x9, 0xff, 0x21, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0xaf, 0xf1, 0xf, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0x0, 0xdf, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x9, + 0xff, 0x50, 0x0, 0x0, 0x0, 0x5f, 0xf8, 0x0, + 0x4f, 0xfd, 0x0, 0x0, 0x0, 0xd, 0xff, 0x20, + 0x0, 0xcf, 0xfa, 0x0, 0x0, 0xa, 0xff, 0x90, + 0x0, 0x3, 0xff, 0xfe, 0x87, 0x8e, 0xff, 0xd0, + 0x0, 0x0, 0x4, 0xef, 0xff, 0xff, 0xff, 0xc1, + 0x0, 0x0, 0x0, 0x1, 0x7c, 0xef, 0xea, 0x50, + 0x0, 0x0, + + /* U+0050 "P" */ + 0x9f, 0xff, 0xff, 0xfe, 0xb6, 0x10, 0x0, 0x9f, + 0xff, 0xff, 0xff, 0xff, 0xe5, 0x0, 0x9f, 0xf6, + 0x55, 0x68, 0xdf, 0xff, 0x40, 0x9f, 0xf1, 0x0, + 0x0, 0x7, 0xff, 0xd0, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0xbf, 0xf3, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x7f, 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x7f, + 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xaf, 0xf2, + 0x9f, 0xf1, 0x0, 0x0, 0x4, 0xff, 0xc0, 0x9f, + 0xf1, 0x0, 0x3, 0x8f, 0xff, 0x30, 0x9f, 0xff, + 0xff, 0xff, 0xff, 0xf5, 0x0, 0x9f, 0xff, 0xff, + 0xff, 0xf9, 0x20, 0x0, 0x9f, 0xf6, 0x65, 0x43, + 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0x0, 0x0, + + /* U+0051 "Q" */ + 0x0, 0x0, 0x4, 0xae, 0xfe, 0xc7, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xaf, 0xff, 0xff, 0xff, 0xe3, + 0x0, 0x0, 0x0, 0xb, 0xff, 0xfa, 0x89, 0xef, + 0xfe, 0x20, 0x0, 0x0, 0x6f, 0xfc, 0x10, 0x0, + 0xb, 0xff, 0xb0, 0x0, 0x0, 0xef, 0xf1, 0x0, + 0x0, 0x0, 0xdf, 0xf3, 0x0, 0x5, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x6f, 0xf9, 0x0, 0xa, 0xff, + 0x20, 0x0, 0x0, 0x0, 0x1f, 0xfd, 0x0, 0xd, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0x0, + 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, + 0x10, 0x1f, 0xfb, 0x0, 0x0, 0x0, 0x0, 0xa, + 0xff, 0x20, 0x1f, 0xfa, 0x0, 0x0, 0x0, 0x0, + 0x9, 0xff, 0x30, 0x1f, 0xfb, 0x0, 0x0, 0x0, + 0x0, 0xa, 0xff, 0x20, 0x1f, 0xfc, 0x0, 0x0, + 0x0, 0x0, 0xb, 0xff, 0x10, 0xf, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0xc, 0xff, + 0x10, 0x0, 0x0, 0x0, 0x1f, 0xfb, 0x0, 0x8, + 0xff, 0x60, 0x0, 0x0, 0x0, 0x6f, 0xf6, 0x0, + 0x3, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xef, 0xf1, + 0x0, 0x0, 0xcf, 0xfa, 0x0, 0x0, 0xb, 0xff, + 0x80, 0x0, 0x0, 0x2f, 0xff, 0xe8, 0x68, 0xef, + 0xfc, 0x0, 0x0, 0x0, 0x3, 0xef, 0xff, 0xff, + 0xff, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x18, 0xcf, + 0xff, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xa, 0xff, 0x30, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x4, 0xff, 0xe5, 0x11, 0x5d, 0x30, + 0x0, 0x0, 0x0, 0x0, 0xaf, 0xff, 0xff, 0xff, + 0xc0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, + 0xfc, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, + 0x65, 0x20, 0x0, + + /* U+0052 "R" */ + 0x6f, 0xff, 0xff, 0xfe, 0xb5, 0x0, 0x0, 0x6f, + 0xff, 0xff, 0xff, 0xff, 0xc1, 0x0, 0x6f, 0xf8, + 0x55, 0x7a, 0xff, 0xfb, 0x0, 0x6f, 0xf4, 0x0, + 0x0, 0x2f, 0xff, 0x20, 0x6f, 0xf4, 0x0, 0x0, + 0x9, 0xff, 0x50, 0x6f, 0xf4, 0x0, 0x0, 0x7, + 0xff, 0x60, 0x6f, 0xf4, 0x0, 0x0, 0x9, 0xff, + 0x30, 0x6f, 0xf4, 0x0, 0x0, 0x3f, 0xfe, 0x0, + 0x6f, 0xf7, 0x34, 0x59, 0xff, 0xf4, 0x0, 0x6f, + 0xff, 0xff, 0xff, 0xfd, 0x40, 0x0, 0x6f, 0xff, + 0xff, 0xff, 0xa0, 0x0, 0x0, 0x6f, 0xf4, 0x2, + 0x9f, 0xfa, 0x0, 0x0, 0x6f, 0xf4, 0x0, 0xa, + 0xff, 0x40, 0x0, 0x6f, 0xf4, 0x0, 0x2, 0xff, + 0xd0, 0x0, 0x6f, 0xf4, 0x0, 0x0, 0xaf, 0xf5, + 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x3f, 0xfc, 0x0, + 0x6f, 0xf4, 0x0, 0x0, 0xb, 0xff, 0x40, 0x6f, + 0xf4, 0x0, 0x0, 0x4, 0xff, 0xb0, 0x6f, 0xf4, + 0x0, 0x0, 0x0, 0xdf, 0xf3, 0x6f, 0xf4, 0x0, + 0x0, 0x0, 0x5f, 0xfa, + + /* U+0053 "S" */ + 0x0, 0x0, 0x5a, 0xdf, 0xfe, 0xda, 0x60, 0x0, + 0x3, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x2, + 0xff, 0xfd, 0x97, 0x78, 0x9c, 0xc0, 0x0, 0xaf, + 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0x30, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x60, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xff, 0xe7, + 0x10, 0x0, 0x0, 0x0, 0x0, 0x5e, 0xff, 0xff, + 0xa3, 0x0, 0x0, 0x0, 0x0, 0x6, 0xcf, 0xff, + 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3a, 0xff, + 0xfd, 0x10, 0x0, 0x0, 0x0, 0x0, 0x2, 0xcf, + 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xef, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, + 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xf0, + 0x11, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xfa, 0x5, + 0xfd, 0xa8, 0x77, 0x8a, 0xef, 0xff, 0x20, 0x5f, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0x20, 0x1, 0x7a, + 0xde, 0xff, 0xfd, 0xa5, 0x0, 0x0, + + /* U+0054 "T" */ + 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcb, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x46, + 0x66, 0x66, 0xef, 0xe6, 0x66, 0x66, 0x40, 0x0, + 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, + 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, + + /* U+0055 "U" */ + 0x5f, 0xf5, 0x0, 0x0, 0x0, 0x4, 0xff, 0x65, + 0xff, 0x50, 0x0, 0x0, 0x0, 0x4f, 0xf6, 0x5f, + 0xf5, 0x0, 0x0, 0x0, 0x4, 0xff, 0x65, 0xff, + 0x50, 0x0, 0x0, 0x0, 0x4f, 0xf6, 0x5f, 0xf5, + 0x0, 0x0, 0x0, 0x4, 0xff, 0x65, 0xff, 0x50, + 0x0, 0x0, 0x0, 0x4f, 0xf6, 0x5f, 0xf5, 0x0, + 0x0, 0x0, 0x4, 0xff, 0x65, 0xff, 0x50, 0x0, + 0x0, 0x0, 0x4f, 0xf6, 0x5f, 0xf5, 0x0, 0x0, + 0x0, 0x4, 0xff, 0x65, 0xff, 0x50, 0x0, 0x0, + 0x0, 0x4f, 0xf6, 0x5f, 0xf5, 0x0, 0x0, 0x0, + 0x4, 0xff, 0x65, 0xff, 0x50, 0x0, 0x0, 0x0, + 0x4f, 0xf6, 0x5f, 0xf5, 0x0, 0x0, 0x0, 0x4, + 0xff, 0x65, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5f, + 0xf5, 0x4f, 0xf7, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x41, 0xff, 0xb0, 0x0, 0x0, 0x0, 0xcf, 0xf0, + 0xc, 0xff, 0x50, 0x0, 0x0, 0x6f, 0xf9, 0x0, + 0x4f, 0xff, 0xa6, 0x56, 0xbf, 0xfe, 0x10, 0x0, + 0x6f, 0xff, 0xff, 0xff, 0xfd, 0x20, 0x0, 0x0, + 0x28, 0xdf, 0xfe, 0xb6, 0x0, 0x0, + + /* U+0056 "V" */ + 0xcf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0xd7, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x5f, + 0xf7, 0x1f, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xb, + 0xff, 0x20, 0xcf, 0xf3, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xc0, 0x7, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x5f, 0xf7, 0x0, 0x2f, 0xfd, 0x0, 0x0, 0x0, + 0xa, 0xff, 0x20, 0x0, 0xcf, 0xf2, 0x0, 0x0, + 0x0, 0xef, 0xc0, 0x0, 0x7, 0xff, 0x70, 0x0, + 0x0, 0x4f, 0xf7, 0x0, 0x0, 0x2f, 0xfc, 0x0, + 0x0, 0x9, 0xff, 0x20, 0x0, 0x0, 0xdf, 0xf1, + 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x7, 0xff, + 0x60, 0x0, 0x3f, 0xf7, 0x0, 0x0, 0x0, 0x2f, + 0xfb, 0x0, 0x8, 0xff, 0x10, 0x0, 0x0, 0x0, + 0xdf, 0xf1, 0x0, 0xdf, 0xc0, 0x0, 0x0, 0x0, + 0x8, 0xff, 0x60, 0x2f, 0xf7, 0x0, 0x0, 0x0, + 0x0, 0x2f, 0xfb, 0x8, 0xff, 0x10, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xf0, 0xdf, 0xc0, 0x0, 0x0, + 0x0, 0x0, 0x8, 0xff, 0x6f, 0xf7, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0x10, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xdf, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xf6, 0x0, + 0x0, 0x0, + + /* U+0057 "W" */ + 0x4f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, + 0x53, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x2f, + 0xf4, 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x2, + 0xff, 0x31, 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xf1, 0xf, 0xf7, 0x0, 0x0, 0x0, 0x0, + 0x4, 0xff, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, + 0x0, 0x5f, 0xf0, 0xd, 0xf9, 0x0, 0x1, 0x41, + 0x0, 0x6, 0xfe, 0x0, 0xcf, 0xa0, 0x0, 0xaf, + 0xb0, 0x0, 0x7f, 0xd0, 0xb, 0xfb, 0x0, 0xf, + 0xff, 0x10, 0x8, 0xfc, 0x0, 0xaf, 0xc0, 0x5, + 0xff, 0xf6, 0x0, 0x8f, 0xb0, 0x9, 0xfd, 0x0, + 0xaf, 0xff, 0xb0, 0x9, 0xfa, 0x0, 0x8f, 0xe0, + 0xf, 0xf7, 0xff, 0x10, 0xaf, 0x90, 0x7, 0xfe, + 0x4, 0xfd, 0xf, 0xf6, 0xb, 0xf8, 0x0, 0x6f, + 0xf0, 0x9f, 0x80, 0xbf, 0xc0, 0xcf, 0x70, 0x5, + 0xff, 0xe, 0xf3, 0x5, 0xff, 0x1d, 0xf6, 0x0, + 0x4f, 0xf5, 0xfe, 0x0, 0xf, 0xf7, 0xdf, 0x50, + 0x3, 0xff, 0xbf, 0x90, 0x0, 0xaf, 0xde, 0xf4, + 0x0, 0x2f, 0xff, 0xf3, 0x0, 0x5, 0xff, 0xff, + 0x30, 0x0, 0xff, 0xfe, 0x0, 0x0, 0xf, 0xff, + 0xf2, 0x0, 0xf, 0xff, 0x90, 0x0, 0x0, 0xaf, + 0xff, 0x10, + + /* U+0058 "X" */ + 0xd, 0xff, 0x40, 0x0, 0x0, 0x0, 0x3f, 0xfd, + 0x0, 0x4f, 0xfd, 0x0, 0x0, 0x0, 0xd, 0xff, + 0x30, 0x0, 0xaf, 0xf7, 0x0, 0x0, 0x7, 0xff, + 0x90, 0x0, 0x1, 0xff, 0xf2, 0x0, 0x1, 0xff, + 0xe1, 0x0, 0x0, 0x6, 0xff, 0xb0, 0x0, 0xaf, + 0xf5, 0x0, 0x0, 0x0, 0xc, 0xff, 0x40, 0x4f, + 0xfb, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0xd, + 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xfd, + 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, + 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, + 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x9f, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x4f, 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xff, 0x5f, 0xfd, 0x0, 0x0, 0x0, 0x0, + 0x8, 0xff, 0x80, 0x9f, 0xf8, 0x0, 0x0, 0x0, + 0x3, 0xff, 0xe0, 0x1, 0xef, 0xf3, 0x0, 0x0, + 0x0, 0xdf, 0xf5, 0x0, 0x6, 0xff, 0xc0, 0x0, + 0x0, 0x7f, 0xfb, 0x0, 0x0, 0xc, 0xff, 0x70, + 0x0, 0x2f, 0xff, 0x20, 0x0, 0x0, 0x3f, 0xff, + 0x20, 0xc, 0xff, 0x80, 0x0, 0x0, 0x0, 0x9f, + 0xfb, 0x6, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x1, + 0xef, 0xf5, + + /* U+0059 "Y" */ + 0xbf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x5, 0xff, + 0xc0, 0x2f, 0xff, 0x10, 0x0, 0x0, 0x0, 0xd, + 0xff, 0x30, 0x9, 0xff, 0x90, 0x0, 0x0, 0x0, + 0x5f, 0xfa, 0x0, 0x1, 0xff, 0xf2, 0x0, 0x0, + 0x0, 0xdf, 0xf2, 0x0, 0x0, 0x7f, 0xfa, 0x0, + 0x0, 0x6, 0xff, 0x80, 0x0, 0x0, 0xe, 0xff, + 0x30, 0x0, 0xe, 0xfe, 0x0, 0x0, 0x0, 0x5, + 0xff, 0xb0, 0x0, 0x7f, 0xf6, 0x0, 0x0, 0x0, + 0x0, 0xcf, 0xf4, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xfc, 0x7, 0xff, 0x50, 0x0, + 0x0, 0x0, 0x0, 0xb, 0xff, 0x5e, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xff, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xfe, + 0x0, 0x0, 0x0, 0x0, + + /* U+005A "Z" */ + 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x8, + 0x88, 0x88, 0x88, 0x88, 0xaf, 0xfe, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xc, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0x2, 0xff, 0xe1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xcf, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x6f, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, + 0xfe, 0x10, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xe1, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x6f, 0xfa, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xfe, 0x10, 0x0, 0x0, 0x0, + 0x0, 0xb, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xef, 0xfa, 0x99, 0x99, 0x99, 0x99, 0x93, 0x5f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x55, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, + + /* U+005B "[" */ + 0xcf, 0xff, 0xff, 0xfb, 0xcf, 0xff, 0xff, 0xfb, + 0xcf, 0xc3, 0x33, 0x32, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xb0, 0x0, 0x0, 0xcf, 0xb0, 0x0, 0x0, + 0xcf, 0xc3, 0x33, 0x32, 0xcf, 0xff, 0xff, 0xfb, + 0xcf, 0xff, 0xff, 0xfb, + + /* U+005C "\\" */ + 0x6f, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, + 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xfe, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0x50, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xe, 0xf9, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x8, 0xff, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x2, 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xbf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x4f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, + 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, + 0x10, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x60, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf3, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfa, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0x10, 0x0, 0x0, 0x0, + 0x0, 0x1, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xaf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, + 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, + 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x70, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x28, 0x81, + + /* U+005D "]" */ + 0xaf, 0xff, 0xff, 0xfd, 0xaf, 0xff, 0xff, 0xfd, + 0x13, 0x33, 0x3c, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x0, 0x0, 0xb, 0xfd, 0x0, 0x0, 0xb, 0xfd, + 0x13, 0x33, 0x3c, 0xfd, 0xaf, 0xff, 0xff, 0xfd, + 0xaf, 0xff, 0xff, 0xfd, + + /* U+005E "^" */ + 0x0, 0x0, 0x0, 0xdf, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0xff, 0x60, 0x0, 0x0, 0x0, + 0x0, 0x1e, 0xfa, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x9, 0xfa, 0xe, 0xf8, 0x0, 0x0, 0x0, 0x2, + 0xff, 0x20, 0x5f, 0xf2, 0x0, 0x0, 0x0, 0xaf, + 0x90, 0x0, 0xcf, 0xb0, 0x0, 0x0, 0x3f, 0xf1, + 0x0, 0x3, 0xff, 0x40, 0x0, 0xc, 0xf8, 0x0, + 0x0, 0xa, 0xfd, 0x0, 0x5, 0xff, 0x10, 0x0, + 0x0, 0x2f, 0xf7, 0x0, 0xdf, 0x70, 0x0, 0x0, + 0x0, 0x8f, 0xf1, + + /* U+005F "_" */ + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, + + /* U+0060 "`" */ + 0x48, 0x84, 0x7f, 0xf6, 0x6f, 0xf5, 0x5f, 0xf4, + 0x4f, 0xf3, 0x3f, 0xf2, 0x2f, 0xf1, 0x1f, 0xf0, + + /* U+0061 "a" */ + 0x1, 0x6a, 0xce, 0xff, 0xc8, 0x10, 0x0, 0xbf, + 0xff, 0xff, 0xff, 0xfe, 0x30, 0xb, 0xfb, 0x85, + 0x57, 0xdf, 0xfe, 0x0, 0x41, 0x0, 0x0, 0x0, + 0xcf, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, + 0x70, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf8, 0x0, + 0x0, 0x0, 0x1, 0x12, 0xff, 0x80, 0x3, 0xad, + 0xff, 0xff, 0xff, 0xf8, 0x9, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x86, 0xff, 0xd5, 0x10, 0x0, 0x1f, + 0xf8, 0xcf, 0xf2, 0x0, 0x0, 0x1, 0xff, 0x8f, + 0xfd, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0xef, 0xf1, + 0x0, 0x0, 0x6f, 0xff, 0x8a, 0xff, 0xd6, 0x47, + 0xdf, 0xff, 0xf8, 0x2e, 0xff, 0xff, 0xff, 0xe3, + 0xdf, 0x80, 0x19, 0xdf, 0xfc, 0x70, 0xd, 0xf8, + + /* U+0062 "b" */ + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x9f, 0xf0, 0x5, 0xbe, 0xfc, 0x50, + 0x0, 0x9f, 0xf0, 0xbf, 0xff, 0xff, 0xf8, 0x0, + 0x9f, 0xfb, 0xff, 0x96, 0x9f, 0xff, 0x40, 0x9f, + 0xff, 0xd2, 0x0, 0x4, 0xff, 0xb0, 0x9f, 0xfe, + 0x10, 0x0, 0x0, 0xcf, 0xf0, 0x9f, 0xf3, 0x0, + 0x0, 0x0, 0x8f, 0xf3, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0x6f, 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x5f, 0xf6, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x5f, + 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x6f, 0xf4, + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x9f, + 0xf1, 0x0, 0x0, 0x1, 0xff, 0xb0, 0x9f, 0xf1, + 0x0, 0x0, 0xa, 0xff, 0x40, 0x9f, 0xfb, 0x64, + 0x36, 0xcf, 0xf9, 0x0, 0x8f, 0xff, 0xff, 0xff, + 0xff, 0x90, 0x0, 0x4, 0x9c, 0xef, 0xfd, 0x93, + 0x0, 0x0, + + /* U+0063 "c" */ + 0x0, 0x0, 0x29, 0xdf, 0xfe, 0xc7, 0x10, 0x0, + 0x9f, 0xff, 0xff, 0xff, 0xf3, 0x0, 0xaf, 0xff, + 0x95, 0x57, 0xaf, 0x30, 0x6f, 0xfd, 0x20, 0x0, + 0x0, 0x0, 0xe, 0xff, 0x20, 0x0, 0x0, 0x0, + 0x3, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xf5, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0x20, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0x8, 0xff, 0x40, 0x0, 0x0, 0x0, + 0x0, 0x5f, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x1, + 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, + 0xb0, 0x0, 0x0, 0x1, 0x10, 0x1e, 0xff, 0xe9, + 0x65, 0x7a, 0xf3, 0x0, 0x2d, 0xff, 0xff, 0xff, + 0xff, 0x30, 0x0, 0x6, 0xbe, 0xff, 0xdb, 0x60, + + /* U+0064 "d" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf8, 0x0, 0x0, 0x29, 0xdf, 0xfe, 0xbf, + 0xf8, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x0, 0x9f, 0xfd, 0x74, 0x57, 0xcf, 0xf8, 0x3, + 0xff, 0xb0, 0x0, 0x0, 0x1f, 0xf8, 0xb, 0xff, + 0x10, 0x0, 0x0, 0x1f, 0xf8, 0xf, 0xfa, 0x0, + 0x0, 0x0, 0x1f, 0xf8, 0x3f, 0xf7, 0x0, 0x0, + 0x0, 0x1f, 0xf8, 0x4f, 0xf5, 0x0, 0x0, 0x0, + 0x1f, 0xf8, 0x5f, 0xf5, 0x0, 0x0, 0x0, 0x1f, + 0xf8, 0x4f, 0xf6, 0x0, 0x0, 0x0, 0x1f, 0xf8, + 0x2f, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0xf8, 0xf, + 0xfd, 0x0, 0x0, 0x3, 0xff, 0xf8, 0xa, 0xff, + 0x50, 0x0, 0x3f, 0xff, 0xf8, 0x3, 0xff, 0xf8, + 0x59, 0xff, 0x8e, 0xf8, 0x0, 0x8f, 0xff, 0xff, + 0xf8, 0xd, 0xf8, 0x0, 0x5, 0xcf, 0xeb, 0x40, + 0xd, 0xf8, + + /* U+0065 "e" */ + 0x0, 0x0, 0x39, 0xdf, 0xec, 0x70, 0x0, 0x0, + 0x0, 0x7f, 0xff, 0xff, 0xff, 0xd2, 0x0, 0x0, + 0x7f, 0xfc, 0x53, 0x4a, 0xff, 0xd0, 0x0, 0x2f, + 0xfc, 0x0, 0x0, 0x7, 0xff, 0x70, 0x9, 0xff, + 0x30, 0x0, 0x0, 0xd, 0xfd, 0x0, 0xef, 0xd0, + 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x1f, 0xfa, 0x11, + 0x11, 0x11, 0x18, 0xff, 0x33, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf4, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x32, 0xff, 0x90, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xbf, 0xf1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x5, 0xff, 0xc1, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xb, 0xff, 0xe9, 0x54, 0x46, 0x8a, + 0x50, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xf7, + 0x0, 0x0, 0x4, 0xad, 0xff, 0xed, 0xb8, 0x20, + + /* U+0066 "f" */ + 0x0, 0x0, 0x0, 0x0, 0x18, 0xcf, 0xff, 0xda, + 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0xff, 0xfe, + 0x0, 0x0, 0x0, 0x1f, 0xff, 0xb6, 0x45, 0x79, + 0x0, 0x0, 0x0, 0x7f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xdf, 0xd0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x3, 0x44, 0x44, 0xef, 0xd4, 0x44, 0x44, 0x41, + 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, + 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xc0, 0x0, 0x0, 0x0, + + /* U+0067 "g" */ + 0x0, 0x1, 0x7c, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x2, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, + 0xef, 0xf8, 0x31, 0x4c, 0xff, 0xa3, 0x20, 0x6f, + 0xf8, 0x0, 0x0, 0xd, 0xff, 0x0, 0x9, 0xff, + 0x20, 0x0, 0x0, 0x8f, 0xf3, 0x0, 0x9f, 0xf1, + 0x0, 0x0, 0x7, 0xff, 0x30, 0x6, 0xff, 0x70, + 0x0, 0x0, 0xdf, 0xf0, 0x0, 0xd, 0xff, 0x71, + 0x3, 0xbf, 0xf8, 0x0, 0x0, 0xaf, 0xff, 0xff, + 0xff, 0xfa, 0x0, 0x0, 0x4f, 0xf8, 0xdf, 0xff, + 0xb5, 0x0, 0x0, 0xb, 0xfb, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0x90, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xbf, 0xfa, 0x66, 0x66, 0x64, 0x20, + 0x0, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd4, + 0x0, 0x1d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, + 0xd, 0xfe, 0x40, 0x0, 0x0, 0x2a, 0xff, 0xa6, + 0xff, 0x50, 0x0, 0x0, 0x0, 0x2f, 0xfb, 0x8f, + 0xf5, 0x0, 0x0, 0x0, 0x7, 0xff, 0x85, 0xff, + 0xf8, 0x53, 0x23, 0x5a, 0xff, 0xe1, 0x9, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xd2, 0x0, 0x3, 0x8c, + 0xef, 0xff, 0xda, 0x50, 0x0, + + /* U+0068 "h" */ + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, + 0x10, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0x0, 0x9, 0xff, 0x10, 0x0, 0x0, + 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, + 0x9, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0x9f, + 0xf0, 0x6, 0xcf, 0xfc, 0x40, 0x9, 0xff, 0x1c, + 0xff, 0xff, 0xff, 0x60, 0x9f, 0xfc, 0xff, 0x86, + 0xaf, 0xff, 0x19, 0xff, 0xfd, 0x10, 0x0, 0x9f, + 0xf6, 0x9f, 0xfd, 0x10, 0x0, 0x2, 0xff, 0x89, + 0xff, 0x30, 0x0, 0x0, 0xf, 0xf9, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, + 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, 0xfa, + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, + 0x10, 0x0, 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, + 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xff, + 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, 0xfa, + + /* U+0069 "i" */ + 0x0, 0x0, 0xa, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x7f, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x1, 0xef, 0xe2, + 0x0, 0x0, 0x0, 0x0, 0x1, 0x31, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, + 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0xef, 0xff, + 0xff, 0xf4, 0x0, 0x0, 0x3, 0x44, 0x48, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x0, + 0x0, 0x0, 0x0, 0x6, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x6f, + 0xf4, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x6, 0xff, 0x40, 0x0, 0x0, 0x0, + 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0x40, 0x0, 0x1, 0x44, 0x44, 0x9f, 0xf7, + 0x44, 0x43, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + + /* U+006A "j" */ + 0x0, 0x0, 0x0, 0x0, 0x3d, 0xe6, 0x0, 0x0, + 0x0, 0x0, 0xc, 0xff, 0xf1, 0x0, 0x0, 0x0, + 0x0, 0xef, 0xff, 0x20, 0x0, 0x0, 0x0, 0x6, + 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0x0, 0x6f, 0xff, + 0xff, 0xff, 0xff, 0xb0, 0x1, 0x44, 0x44, 0x44, + 0x4f, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0xb0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfb, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfb, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xf9, 0x0, 0x0, 0x0, + 0x0, 0x5, 0xff, 0x60, 0x2, 0x0, 0x0, 0x1, + 0xdf, 0xf1, 0x0, 0xfc, 0x85, 0x57, 0xef, 0xf8, + 0x0, 0xf, 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, + 0x5a, 0xdf, 0xfe, 0xa4, 0x0, 0x0, + + /* U+006B "k" */ + 0x4f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, + 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, + 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, + 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf6, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0x60, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf6, 0x0, + 0x0, 0x4, 0xff, 0xf4, 0x4, 0xff, 0x60, 0x0, + 0x3, 0xff, 0xf4, 0x0, 0x4f, 0xf6, 0x0, 0x2, + 0xef, 0xf4, 0x0, 0x4, 0xff, 0x60, 0x2, 0xef, + 0xf5, 0x0, 0x0, 0x4f, 0xf6, 0x1, 0xef, 0xf5, + 0x0, 0x0, 0x4, 0xff, 0x61, 0xdf, 0xf6, 0x0, + 0x0, 0x0, 0x4f, 0xf7, 0xcf, 0xf6, 0x0, 0x0, + 0x0, 0x4, 0xff, 0xdf, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x4f, 0xf6, 0xbf, 0xf8, 0x0, 0x0, 0x0, + 0x4, 0xff, 0x60, 0xdf, 0xf6, 0x0, 0x0, 0x0, + 0x4f, 0xf6, 0x2, 0xef, 0xf4, 0x0, 0x0, 0x4, + 0xff, 0x60, 0x4, 0xff, 0xf3, 0x0, 0x0, 0x4f, + 0xf6, 0x0, 0x6, 0xff, 0xe2, 0x0, 0x4, 0xff, + 0x60, 0x0, 0x9, 0xff, 0xd1, 0x0, 0x4f, 0xf6, + 0x0, 0x0, 0xc, 0xff, 0xc0, 0x4, 0xff, 0x60, + 0x0, 0x0, 0x1d, 0xff, 0xa0, + + /* U+006C "l" */ + 0xe, 0xff, 0xff, 0xff, 0x40, 0x0, 0x0, 0xef, + 0xff, 0xff, 0xf4, 0x0, 0x0, 0x3, 0x33, 0x38, + 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf4, + 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0x40, 0x0, + 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x0, + 0x0, 0x6, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x0, + 0x0, 0x0, 0x0, 0x6, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, 0x6f, + 0xf4, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x6, 0xff, 0x40, 0x0, 0x0, 0x0, + 0x0, 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0x40, 0x0, 0x1, 0x44, 0x44, 0x9f, 0xf7, + 0x44, 0x43, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + + /* U+006D "m" */ + 0xaf, 0x60, 0x9e, 0xe5, 0x0, 0x9e, 0xe5, 0xa, + 0xf6, 0x8f, 0xff, 0xf1, 0x9f, 0xff, 0xf2, 0xaf, + 0x9f, 0xb5, 0xff, 0x7f, 0xb6, 0xff, 0x7a, 0xff, + 0xe1, 0xc, 0xff, 0xe0, 0xd, 0xfa, 0xaf, 0xf7, + 0x0, 0xbf, 0xf6, 0x0, 0xbf, 0xaa, 0xfe, 0x0, + 0xb, 0xfe, 0x0, 0xb, 0xfb, 0xaf, 0xc0, 0x0, + 0xbf, 0xb0, 0x0, 0xbf, 0xba, 0xfc, 0x0, 0xb, + 0xfb, 0x0, 0xb, 0xfb, 0xaf, 0xc0, 0x0, 0xbf, + 0xb0, 0x0, 0xbf, 0xba, 0xfc, 0x0, 0xb, 0xfb, + 0x0, 0xb, 0xfb, 0xaf, 0xc0, 0x0, 0xbf, 0xb0, + 0x0, 0xbf, 0xba, 0xfc, 0x0, 0xb, 0xfb, 0x0, + 0xb, 0xfb, 0xaf, 0xc0, 0x0, 0xbf, 0xb0, 0x0, + 0xbf, 0xba, 0xfc, 0x0, 0xb, 0xfb, 0x0, 0xb, + 0xfb, 0xaf, 0xc0, 0x0, 0xbf, 0xb0, 0x0, 0xbf, + 0xba, 0xfc, 0x0, 0xb, 0xfb, 0x0, 0xb, 0xfb, + + /* U+006E "n" */ + 0x9f, 0xc0, 0x6, 0xcf, 0xfc, 0x50, 0x9, 0xfd, + 0x1c, 0xff, 0xff, 0xff, 0x60, 0x9f, 0xec, 0xfe, + 0x86, 0xaf, 0xff, 0x19, 0xff, 0xfc, 0x10, 0x0, + 0x9f, 0xf6, 0x9f, 0xfd, 0x10, 0x0, 0x2, 0xff, + 0x89, 0xff, 0x30, 0x0, 0x0, 0xf, 0xf9, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, + 0x0, 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, + 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xff, 0xa9, + 0xff, 0x10, 0x0, 0x0, 0xf, 0xfa, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, + 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, 0xfa, + + /* U+006F "o" */ + 0x0, 0x0, 0x5a, 0xef, 0xec, 0x71, 0x0, 0x0, + 0x1, 0xbf, 0xff, 0xff, 0xff, 0xe4, 0x0, 0x0, + 0xcf, 0xfc, 0x75, 0x6c, 0xff, 0xf2, 0x0, 0x8f, + 0xf9, 0x0, 0x0, 0x8, 0xff, 0xb0, 0xe, 0xfd, + 0x0, 0x0, 0x0, 0xc, 0xff, 0x24, 0xff, 0x70, + 0x0, 0x0, 0x0, 0x6f, 0xf6, 0x7f, 0xf4, 0x0, + 0x0, 0x0, 0x2, 0xff, 0x89, 0xff, 0x20, 0x0, + 0x0, 0x0, 0x1f, 0xfa, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0x1, 0xff, 0x98, 0xff, 0x30, 0x0, 0x0, + 0x0, 0x3f, 0xf8, 0x5f, 0xf6, 0x0, 0x0, 0x0, + 0x6, 0xff, 0x51, 0xff, 0xc0, 0x0, 0x0, 0x0, + 0xcf, 0xf0, 0xb, 0xff, 0x80, 0x0, 0x0, 0x8f, + 0xf8, 0x0, 0x2f, 0xff, 0xc6, 0x56, 0xcf, 0xfd, + 0x0, 0x0, 0x3e, 0xff, 0xff, 0xff, 0xfc, 0x10, + 0x0, 0x0, 0x7, 0xce, 0xfe, 0xb5, 0x0, 0x0, + + /* U+0070 "p" */ + 0x9f, 0xc0, 0x6, 0xce, 0xfc, 0x50, 0x0, 0x9f, + 0xd0, 0xbf, 0xff, 0xff, 0xf8, 0x0, 0x9f, 0xeb, + 0xff, 0x96, 0x9f, 0xff, 0x40, 0x9f, 0xff, 0xd2, + 0x0, 0x4, 0xff, 0xb0, 0x9f, 0xfe, 0x10, 0x0, + 0x0, 0xcf, 0xf0, 0x9f, 0xf3, 0x0, 0x0, 0x0, + 0x8f, 0xf3, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x6f, + 0xf5, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x5f, 0xf6, + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x5f, 0xf5, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0x6f, 0xf4, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x9f, 0xf1, 0x0, + 0x0, 0x1, 0xff, 0xc0, 0x9f, 0xf1, 0x0, 0x0, + 0xa, 0xff, 0x40, 0x9f, 0xfb, 0x64, 0x36, 0xdf, + 0xfa, 0x0, 0x9f, 0xff, 0xff, 0xff, 0xff, 0x90, + 0x0, 0x9f, 0xfc, 0xef, 0xfd, 0x93, 0x0, 0x0, + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x9f, 0xf1, 0x0, 0x0, 0x0, + 0x0, 0x0, + + /* U+0071 "q" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x39, 0xdf, 0xfd, 0xa9, 0xd8, 0x0, 0x8, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x9f, 0xfd, + 0x64, 0x46, 0xcf, 0xf8, 0x3, 0xff, 0xb0, 0x0, + 0x0, 0x1f, 0xf8, 0xb, 0xff, 0x10, 0x0, 0x0, + 0x1f, 0xf8, 0xf, 0xfa, 0x0, 0x0, 0x0, 0x1f, + 0xf8, 0x3f, 0xf7, 0x0, 0x0, 0x0, 0x1f, 0xf8, + 0x4f, 0xf5, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x5f, + 0xf6, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x4f, 0xf7, + 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x2f, 0xf9, 0x0, + 0x0, 0x0, 0x7f, 0xf8, 0xf, 0xfd, 0x0, 0x0, + 0x3, 0xff, 0xf8, 0xb, 0xff, 0x50, 0x0, 0x3f, + 0xff, 0xf8, 0x3, 0xff, 0xf8, 0x59, 0xff, 0x8f, + 0xf8, 0x0, 0x8f, 0xff, 0xff, 0xf8, 0xf, 0xf8, + 0x0, 0x5, 0xcf, 0xeb, 0x40, 0x1f, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, + 0xf8, + + /* U+0072 "r" */ + 0xff, 0x70, 0x6, 0xcf, 0xeb, 0x30, 0xf, 0xf7, + 0x1b, 0xff, 0xff, 0xff, 0x40, 0xff, 0x9c, 0xff, + 0x86, 0xaf, 0xfe, 0xf, 0xff, 0xfc, 0x10, 0x0, + 0xaf, 0xf4, 0xff, 0xfd, 0x0, 0x0, 0x4, 0xff, + 0x7f, 0xfe, 0x10, 0x0, 0x0, 0x2f, 0xf8, 0xff, + 0xb0, 0x0, 0x0, 0x0, 0x44, 0x2f, 0xfb, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0xf, + 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xff, 0xb0, 0x0, 0x0, 0x0, + 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, + + /* U+0073 "s" */ + 0x0, 0x4, 0xad, 0xff, 0xed, 0xb4, 0x0, 0xa, + 0xff, 0xff, 0xff, 0xff, 0x70, 0x7, 0xff, 0xd7, + 0x44, 0x57, 0xa5, 0x0, 0xef, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xef, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0xfc, 0x61, 0x0, 0x0, 0x0, 0x7, 0xff, + 0xff, 0xfb, 0x50, 0x0, 0x0, 0x1, 0x8d, 0xff, + 0xff, 0xd2, 0x0, 0x0, 0x0, 0x3, 0x8e, 0xff, + 0xe0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf6, 0x0, 0x0, + 0x0, 0x0, 0x9, 0xff, 0x44, 0xea, 0x76, 0x55, + 0x6b, 0xff, 0xd0, 0x4f, 0xff, 0xff, 0xff, 0xff, + 0xd2, 0x1, 0x8b, 0xde, 0xff, 0xea, 0x50, 0x0, + + /* U+0074 "t" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x5a, 0xc0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xc, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xcf, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xc, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xcf, 0xd0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xa0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfa, 0x4, 0x44, 0x4d, 0xfe, + 0x44, 0x44, 0x44, 0x30, 0x0, 0x0, 0xcf, 0xd0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xc, 0xfd, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xc, 0xfe, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xbf, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x8, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x3f, 0xff, 0xa6, 0x56, 0x87, 0x0, 0x0, + 0x0, 0x7f, 0xff, 0xff, 0xff, 0xa0, 0x0, 0x0, + 0x0, 0x4a, 0xef, 0xfe, 0xc6, + + /* U+0075 "u" */ + 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, + 0x10, 0x0, 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, + 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, + 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x0, 0xff, + 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, 0xfa, 0x9f, + 0xf1, 0x0, 0x0, 0x0, 0xff, 0xa9, 0xff, 0x10, + 0x0, 0x0, 0xf, 0xfa, 0x9f, 0xf1, 0x0, 0x0, + 0x0, 0xff, 0xa9, 0xff, 0x10, 0x0, 0x0, 0xf, + 0xfa, 0x9f, 0xf1, 0x0, 0x0, 0x1, 0xff, 0xa8, + 0xff, 0x30, 0x0, 0x0, 0xcf, 0xfa, 0x5f, 0xf9, + 0x0, 0x1, 0xcf, 0xff, 0xa0, 0xff, 0xfa, 0x67, + 0xef, 0xdd, 0xfa, 0x6, 0xff, 0xff, 0xff, 0xc1, + 0xcf, 0xa0, 0x4, 0xcf, 0xfd, 0x70, 0xb, 0xfa, + + /* U+0076 "v" */ + 0xdf, 0xf2, 0x0, 0x0, 0x0, 0x2, 0xff, 0xb7, + 0xff, 0x80, 0x0, 0x0, 0x0, 0x7f, 0xf6, 0x1f, + 0xfd, 0x0, 0x0, 0x0, 0xd, 0xff, 0x0, 0xbf, + 0xf3, 0x0, 0x0, 0x2, 0xff, 0xa0, 0x5, 0xff, + 0x90, 0x0, 0x0, 0x8f, 0xf4, 0x0, 0xe, 0xfe, + 0x0, 0x0, 0xe, 0xfe, 0x0, 0x0, 0x9f, 0xf4, + 0x0, 0x3, 0xff, 0x80, 0x0, 0x3, 0xff, 0xa0, + 0x0, 0x9f, 0xf2, 0x0, 0x0, 0xd, 0xff, 0x0, + 0xe, 0xfc, 0x0, 0x0, 0x0, 0x7f, 0xf5, 0x4, + 0xff, 0x60, 0x0, 0x0, 0x1, 0xff, 0xb0, 0xaf, + 0xf0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x1e, 0xfa, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf9, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x0, + 0x0, 0x0, 0x0, 0x9, 0xff, 0xf8, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x3f, 0xff, 0x20, 0x0, 0x0, + + /* U+0077 "w" */ + 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, + 0x63, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x4f, + 0xf4, 0x1f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x6, + 0xff, 0x20, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x7f, 0xf0, 0xd, 0xfa, 0x0, 0xa, 0xf9, 0x0, + 0x9, 0xfe, 0x0, 0xbf, 0xc0, 0x0, 0xef, 0xe0, + 0x0, 0xbf, 0xb0, 0x8, 0xfe, 0x0, 0x3f, 0xff, + 0x40, 0xc, 0xf9, 0x0, 0x6f, 0xf0, 0x8, 0xff, + 0xf9, 0x0, 0xef, 0x70, 0x4, 0xff, 0x20, 0xdf, + 0x8f, 0xe0, 0xf, 0xf5, 0x0, 0x2f, 0xf3, 0x2f, + 0xe1, 0xff, 0x42, 0xff, 0x30, 0x0, 0xff, 0x57, + 0xf9, 0xb, 0xf9, 0x3f, 0xf0, 0x0, 0xd, 0xf7, + 0xcf, 0x40, 0x6f, 0xe5, 0xfe, 0x0, 0x0, 0xbf, + 0xaf, 0xf0, 0x1, 0xff, 0xbf, 0xc0, 0x0, 0x9, + 0xff, 0xfa, 0x0, 0xb, 0xff, 0xfa, 0x0, 0x0, + 0x7f, 0xff, 0x50, 0x0, 0x6f, 0xff, 0x80, 0x0, + 0x5, 0xff, 0xf0, 0x0, 0x1, 0xff, 0xf5, 0x0, + + /* U+0078 "x" */ + 0x5f, 0xfe, 0x10, 0x0, 0x0, 0xb, 0xff, 0x80, + 0x9, 0xff, 0xa0, 0x0, 0x0, 0x5f, 0xfc, 0x0, + 0x0, 0xdf, 0xf5, 0x0, 0x1, 0xef, 0xf2, 0x0, + 0x0, 0x3f, 0xfe, 0x10, 0x9, 0xff, 0x60, 0x0, + 0x0, 0x7, 0xff, 0xa0, 0x3f, 0xfa, 0x0, 0x0, + 0x0, 0x0, 0xcf, 0xf4, 0xdf, 0xe1, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xff, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x6, 0xff, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x3f, 0xff, 0xff, 0x40, 0x0, 0x0, + 0x0, 0x0, 0xdf, 0xf4, 0xff, 0xe1, 0x0, 0x0, + 0x0, 0xa, 0xff, 0x70, 0x6f, 0xfb, 0x0, 0x0, + 0x0, 0x5f, 0xfc, 0x0, 0xb, 0xff, 0x80, 0x0, + 0x2, 0xff, 0xf2, 0x0, 0x1, 0xff, 0xf4, 0x0, + 0xc, 0xff, 0x70, 0x0, 0x0, 0x6f, 0xfe, 0x10, + 0x9f, 0xfc, 0x0, 0x0, 0x0, 0xb, 0xff, 0xb0, + + /* U+0079 "y" */ + 0xc, 0xff, 0x20, 0x0, 0x0, 0x0, 0x2f, 0xfb, + 0x6, 0xff, 0x80, 0x0, 0x0, 0x0, 0x7f, 0xf6, + 0x1, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xdf, 0xf0, + 0x0, 0xaf, 0xf4, 0x0, 0x0, 0x2, 0xff, 0xa0, + 0x0, 0x3f, 0xfa, 0x0, 0x0, 0x8, 0xff, 0x40, + 0x0, 0xd, 0xff, 0x10, 0x0, 0xd, 0xfe, 0x0, + 0x0, 0x7, 0xff, 0x60, 0x0, 0x3f, 0xf8, 0x0, + 0x0, 0x1, 0xff, 0xc0, 0x0, 0x9f, 0xf2, 0x0, + 0x0, 0x0, 0xbf, 0xf2, 0x0, 0xef, 0xc0, 0x0, + 0x0, 0x0, 0x4f, 0xf8, 0x4, 0xff, 0x60, 0x0, + 0x0, 0x0, 0xe, 0xfe, 0x9, 0xff, 0x10, 0x0, + 0x0, 0x0, 0x8, 0xff, 0x4f, 0xfa, 0x0, 0x0, + 0x0, 0x0, 0x2, 0xff, 0xdf, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xbf, 0xff, 0xe0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x5f, 0xff, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xf, 0xff, 0x10, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x6f, 0xfa, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0xef, 0xf2, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1c, 0xff, 0x70, 0x0, 0x0, 0x0, + 0x7, 0x69, 0xff, 0xfb, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xfe, 0xa4, 0x0, 0x0, 0x0, 0x0, 0x0, + + /* U+007A "z" */ + 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x35, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf3, 0x14, 0x44, 0x44, + 0x44, 0x6f, 0xfe, 0x10, 0x0, 0x0, 0x0, 0xc, + 0xff, 0x30, 0x0, 0x0, 0x0, 0x8, 0xff, 0x80, + 0x0, 0x0, 0x0, 0x4, 0xff, 0xc0, 0x0, 0x0, + 0x0, 0x1, 0xef, 0xe1, 0x0, 0x0, 0x0, 0x0, + 0xbf, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf9, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0x0, 0x0, + 0x0, 0x0, 0xd, 0xff, 0x20, 0x0, 0x0, 0x0, + 0xa, 0xff, 0x60, 0x0, 0x0, 0x0, 0x6, 0xff, + 0xa0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xf5, 0x44, + 0x44, 0x44, 0x43, 0x8f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, + + /* U+007B "{" */ + 0x0, 0x0, 0x0, 0x17, 0xcf, 0xf9, 0x0, 0x0, + 0x2, 0xef, 0xff, 0xf9, 0x0, 0x0, 0xb, 0xff, + 0xc5, 0x31, 0x0, 0x0, 0x1f, 0xfb, 0x0, 0x0, + 0x0, 0x0, 0x4f, 0xf5, 0x0, 0x0, 0x0, 0x0, + 0x4f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf2, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0x5f, 0xf2, 0x0, 0x0, 0x0, 0x0, + 0x6f, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xe0, + 0x0, 0x0, 0x13, 0x49, 0xff, 0x60, 0x0, 0x0, + 0x8f, 0xff, 0xc5, 0x0, 0x0, 0x0, 0x8f, 0xff, + 0xe9, 0x0, 0x0, 0x0, 0x0, 0x28, 0xff, 0x90, + 0x0, 0x0, 0x0, 0x0, 0xaf, 0xf0, 0x0, 0x0, + 0x0, 0x0, 0x6f, 0xf2, 0x0, 0x0, 0x0, 0x0, + 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf3, 0x0, 0x0, + 0x0, 0x0, 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, + 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf3, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, + 0xa, 0xff, 0xc5, 0x31, 0x0, 0x0, 0x1, 0xdf, + 0xff, 0xf9, 0x0, 0x0, 0x0, 0x7, 0xcf, 0xf9, + + /* U+007C "|" */ + 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, + 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, + 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, + 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, + 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, + 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, 0xbf, 0xcb, 0xfc, + + /* U+007D "}" */ + 0x8f, 0xfc, 0x81, 0x0, 0x0, 0x0, 0x8f, 0xff, + 0xfe, 0x20, 0x0, 0x0, 0x13, 0x5c, 0xff, 0xc0, + 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf1, 0x0, 0x0, + 0x0, 0x0, 0x5f, 0xf4, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf7, 0x0, 0x0, 0x0, 0x0, 0xe, 0xfc, + 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xb5, 0x31, + 0x0, 0x0, 0x0, 0x6c, 0xff, 0xf9, 0x0, 0x0, + 0x0, 0x7e, 0xff, 0xf9, 0x0, 0x0, 0x7, 0xff, + 0x72, 0x0, 0x0, 0x0, 0xe, 0xfa, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf6, 0x0, 0x0, 0x0, 0x0, + 0x1f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf5, 0x0, 0x0, + 0x0, 0x0, 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, + 0x2f, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xf5, + 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf4, 0x0, 0x0, + 0x0, 0x0, 0xbf, 0xf1, 0x0, 0x0, 0x13, 0x5c, + 0xff, 0xb0, 0x0, 0x0, 0x8f, 0xff, 0xfe, 0x10, + 0x0, 0x0, 0x8f, 0xfc, 0x71, 0x0, 0x0, 0x0, + + /* U+007E "~" */ + 0x0, 0x1, 0x67, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x5, 0xff, 0xff, 0xb1, 0x0, 0x0, 0x39, + 0x90, 0x3, 0xff, 0xff, 0xff, 0xd1, 0x0, 0x7, + 0xff, 0x0, 0xaf, 0xf3, 0x19, 0xff, 0xd2, 0x0, + 0xaf, 0xd0, 0xe, 0xf9, 0x0, 0x7, 0xff, 0xe8, + 0xaf, 0xf8, 0x0, 0xff, 0x70, 0x0, 0x7, 0xff, + 0xff, 0xfd, 0x0, 0x1, 0x10, 0x0, 0x0, 0x3, + 0xcf, 0xe9, 0x10, 0x0, + + /* U+007F "" */ + + /* U+4E2D "中" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xe, 0xfa, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xef, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xfa, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x33, + 0x33, 0x33, 0x33, 0x33, 0x3f, 0xfb, 0x33, 0x33, + 0x33, 0x33, 0x33, 0x32, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x7f, + 0xf0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0x97, 0xff, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xfa, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xf9, 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xa0, 0x0, 0x0, 0x0, 0x0, 0xef, 0x97, + 0xff, 0x0, 0x0, 0x0, 0x0, 0xe, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0xe, 0xf9, 0x7f, 0xf0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0xef, 0x97, 0xff, 0x0, 0x0, 0x0, 0x0, + 0xe, 0xfa, 0x0, 0x0, 0x0, 0x0, 0xe, 0xf9, + 0x7f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xa0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0x97, 0xff, 0x54, + 0x44, 0x44, 0x44, 0x4f, 0xfc, 0x44, 0x44, 0x44, + 0x44, 0x4f, 0xf9, 0x7f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x97, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x7f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0x94, 0x99, 0x0, 0x0, 0x0, + 0x0, 0xe, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x8, + 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, + 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xe, 0xfa, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xef, 0xa0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, + 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xe, 0xfa, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xef, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xef, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, + + /* U+6587 "æ–‡" */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x35, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xf2, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xb0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xfa, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0xca, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x50, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0, 0xee, 0xee, 0xef, + 0xff, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, + 0xff, 0xee, 0xee, 0xe0, 0x0, 0x0, 0x0, 0x3f, + 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xff, + 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xfb, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xfc, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf0, + 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x60, + 0x0, 0x0, 0x0, 0x0, 0x6f, 0xf2, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xfd, 0x0, + 0x0, 0x0, 0x0, 0xd, 0xfc, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf4, 0x0, + 0x0, 0x0, 0x4, 0xff, 0x50, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xd0, 0x0, + 0x0, 0x0, 0xcf, 0xe0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0, + 0x0, 0x6f, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0x30, 0x0, + 0x1f, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x1e, 0xfe, 0x10, 0xd, + 0xff, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x3f, 0xfd, 0x1b, 0xff, + 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0x90, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x9f, 0xff, 0xc0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0x70, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x4, 0xcf, 0xff, 0xbf, 0xff, 0xd6, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x4b, 0xff, 0xfe, 0x40, 0x4e, 0xff, 0xfe, 0x71, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xdf, + 0xff, 0xf8, 0x0, 0x0, 0x8, 0xff, 0xff, 0xfb, + 0x50, 0x0, 0x0, 0x0, 0x5, 0xaf, 0xff, 0xff, + 0x91, 0x0, 0x0, 0x0, 0x1, 0x9f, 0xff, 0xff, + 0xfb, 0x62, 0x1, 0xaf, 0xff, 0xff, 0xe8, 0x10, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0xef, 0xff, + 0xff, 0xd0, 0xa, 0xff, 0xfc, 0x60, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5c, 0xff, + 0xe2, 0x0, 0xc, 0x93, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x74, + 0x0 +}; + + +static const sgl_font_table_t consolas32_tab[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 273, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 273, .box_w = 5, .box_h = 22, .ofs_x = 6, .ofs_y = 0}, + {.bitmap_index = 55, .adv_w = 273, .box_w = 11, .box_h = 8, .ofs_x = 3, .ofs_y = 14}, + {.bitmap_index = 99, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 269, .adv_w = 273, .box_w = 15, .box_h = 28, .ofs_x = 1, .ofs_y = -4}, + {.bitmap_index = 479, .adv_w = 273, .box_w = 17, .box_h = 22, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 666, .adv_w = 273, .box_w = 18, .box_h = 22, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 864, .adv_w = 273, .box_w = 5, .box_h = 8, .ofs_x = 6, .ofs_y = 14}, + {.bitmap_index = 884, .adv_w = 273, .box_w = 10, .box_h = 31, .ofs_x = 4, .ofs_y = -7}, + {.bitmap_index = 1039, .adv_w = 273, .box_w = 10, .box_h = 31, .ofs_x = 3, .ofs_y = -7}, + {.bitmap_index = 1194, .adv_w = 273, .box_w = 13, .box_h = 14, .ofs_x = 2, .ofs_y = 8}, + {.bitmap_index = 1285, .adv_w = 273, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1405, .adv_w = 273, .box_w = 8, .box_h = 11, .ofs_x = 3, .ofs_y = -5}, + {.bitmap_index = 1449, .adv_w = 273, .box_w = 10, .box_h = 3, .ofs_x = 4, .ofs_y = 7}, + {.bitmap_index = 1464, .adv_w = 273, .box_w = 6, .box_h = 6, .ofs_x = 5, .ofs_y = 0}, + {.bitmap_index = 1482, .adv_w = 273, .box_w = 17, .box_h = 22, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1669, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1819, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 1959, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2099, .adv_w = 273, .box_w = 13, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2229, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2399, .adv_w = 273, .box_w = 13, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 2529, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2679, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2829, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2979, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3129, .adv_w = 273, .box_w = 5, .box_h = 16, .ofs_x = 6, .ofs_y = 0}, + {.bitmap_index = 3169, .adv_w = 273, .box_w = 9, .box_h = 22, .ofs_x = 3, .ofs_y = -6}, + {.bitmap_index = 3268, .adv_w = 273, .box_w = 12, .box_h = 19, .ofs_x = 2, .ofs_y = -1}, + {.bitmap_index = 3382, .adv_w = 273, .box_w = 14, .box_h = 8, .ofs_x = 2, .ofs_y = 5}, + {.bitmap_index = 3438, .adv_w = 273, .box_w = 12, .box_h = 19, .ofs_x = 3, .ofs_y = -1}, + {.bitmap_index = 3552, .adv_w = 273, .box_w = 10, .box_h = 22, .ofs_x = 4, .ofs_y = 0}, + {.bitmap_index = 3662, .adv_w = 273, .box_w = 17, .box_h = 28, .ofs_x = 0, .ofs_y = -6}, + {.bitmap_index = 3900, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4070, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 4210, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4360, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4510, .adv_w = 273, .box_w = 12, .box_h = 20, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 4630, .adv_w = 273, .box_w = 12, .box_h = 20, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 4750, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4900, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5050, .adv_w = 273, .box_w = 13, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5180, .adv_w = 273, .box_w = 12, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5300, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 5440, .adv_w = 273, .box_w = 12, .box_h = 20, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 5560, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 5730, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 5880, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 6050, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 6190, .adv_w = 273, .box_w = 18, .box_h = 27, .ofs_x = 0, .ofs_y = -7}, + {.bitmap_index = 6433, .adv_w = 273, .box_w = 14, .box_h = 20, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 6573, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 6723, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 6873, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 7023, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 7193, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 7363, .adv_w = 273, .box_w = 17, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 7533, .adv_w = 273, .box_w = 18, .box_h = 20, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 7713, .adv_w = 273, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 7863, .adv_w = 273, .box_w = 8, .box_h = 29, .ofs_x = 5, .ofs_y = -6}, + {.bitmap_index = 7979, .adv_w = 273, .box_w = 14, .box_h = 26, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 8161, .adv_w = 273, .box_w = 8, .box_h = 29, .ofs_x = 4, .ofs_y = -6}, + {.bitmap_index = 8277, .adv_w = 273, .box_w = 15, .box_h = 10, .ofs_x = 1, .ofs_y = 10}, + {.bitmap_index = 8352, .adv_w = 273, .box_w = 18, .box_h = 3, .ofs_x = 0, .ofs_y = -6}, + {.bitmap_index = 8379, .adv_w = 127, .box_w = 4, .box_h = 8, .ofs_x = 2, .ofs_y = 17}, + {.bitmap_index = 8395, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 8499, .adv_w = 273, .box_w = 14, .box_h = 22, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 8653, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 8757, .adv_w = 273, .box_w = 14, .box_h = 22, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 8911, .adv_w = 273, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 9031, .adv_w = 273, .box_w = 16, .box_h = 22, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 9207, .adv_w = 273, .box_w = 15, .box_h = 22, .ofs_x = 1, .ofs_y = -6}, + {.bitmap_index = 9372, .adv_w = 273, .box_w = 13, .box_h = 22, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 9515, .adv_w = 273, .box_w = 13, .box_h = 22, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 9658, .adv_w = 273, .box_w = 13, .box_h = 28, .ofs_x = 1, .ofs_y = -6}, + {.bitmap_index = 9840, .adv_w = 273, .box_w = 15, .box_h = 22, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 10005, .adv_w = 273, .box_w = 13, .box_h = 22, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 10148, .adv_w = 273, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 10268, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 10372, .adv_w = 273, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 10492, .adv_w = 273, .box_w = 14, .box_h = 22, .ofs_x = 2, .ofs_y = -6}, + {.bitmap_index = 10646, .adv_w = 273, .box_w = 14, .box_h = 23, .ofs_x = 1, .ofs_y = -6}, + {.bitmap_index = 10807, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 10911, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 11015, .adv_w = 273, .box_w = 15, .box_h = 22, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 11180, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 11284, .adv_w = 273, .box_w = 15, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 11404, .adv_w = 273, .box_w = 17, .box_h = 16, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 11540, .adv_w = 273, .box_w = 16, .box_h = 16, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 11668, .adv_w = 273, .box_w = 16, .box_h = 22, .ofs_x = 0, .ofs_y = -6}, + {.bitmap_index = 11844, .adv_w = 273, .box_w = 13, .box_h = 16, .ofs_x = 2, .ofs_y = 0}, + {.bitmap_index = 11948, .adv_w = 273, .box_w = 12, .box_h = 28, .ofs_x = 2, .ofs_y = -6}, + {.bitmap_index = 12116, .adv_w = 273, .box_w = 3, .box_h = 32, .ofs_x = 7, .ofs_y = -6}, + {.bitmap_index = 12164, .adv_w = 273, .box_w = 12, .box_h = 28, .ofs_x = 3, .ofs_y = -6}, + {.bitmap_index = 12332, .adv_w = 273, .box_w = 17, .box_h = 7, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 12392, .adv_w = 273, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 12392, .adv_w = 496, .box_w = 27, .box_h = 31, .ofs_x = 2, .ofs_y = -4}, + {.bitmap_index = 12811, .adv_w = 496, .box_w = 31, .box_h = 30, .ofs_x = 0, .ofs_y = -4} +}; + +static const uint32_t unicode_list_1[] = { + 0x0, 0x175a +}; + +static const sgl_font_unicode_t consolas34_unicode[] = { + { .offset = 32, .len = 96, .list = NULL, .tab_offset = 1, }, + { .offset = 20013, .len = 2, .list = unicode_list_1, .tab_offset = 97, }, +}; + +const sgl_font_t consolas32 = { + .bitmap = consolas32_bitmap, + .table = consolas32_tab, + .font_table_size = SGL_ARRAY_SIZE(consolas32_tab), + .font_height = 34, + .base_line = 7, + .bpp = 4, + .unicode = consolas34_unicode, + .unicode_num = 2, +}; + + +#endif // !CONFIG_SGL_FONT_CONSOLAS32 diff --git a/User/system/sgl/fonts/sgl_ascii_song23.c b/User/system/sgl/fonts/sgl_ascii_song23.c new file mode 100644 index 0000000..f415d6c --- /dev/null +++ b/User/system/sgl/fonts/sgl_ascii_song23.c @@ -0,0 +1,1740 @@ +/* source/fonts/sgl_song23.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * + * Email: 1477153217@qq.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + + +#if (CONFIG_SGL_FONT_SONG23) + +/* +*.box_h: 24 pixel +*/ +static const uint8_t sgl_ascii_song23_bitmap[] = { +/* */ + +/* ! */ +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... +0x00,0x00,0xaf,0xe0,0x00,0x00, //....%@@..... +0x00,0x00,0xaf,0xe0,0x00,0x00, //....%@@..... +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... +0x00,0x00,0x5e,0xc0,0x00,0x00, //....+@%..... +0x00,0x00,0x3e,0xa0,0x00,0x00, //.....@%..... +0x00,0x00,0x3c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x3c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x0c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x0a,0x50,0x00,0x00, //.....%+..... +0x00,0x00,0x0a,0x50,0x00,0x00, //.....%+..... +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... +0x00,0x00,0xcf,0xe5,0x00,0x00, //....%@@+.... +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... + + +/* " */ +0x00,0x03,0xee,0x58,0xec,0x00, //....@@++@%.. +0x00,0x0a,0xfe,0x5e,0xfe,0x00, //...%@@+@@@.. +0x00,0x3e,0xe8,0x8e,0xe3,0x00, //...@@++@@... +0x00,0xae,0x80,0xee,0x30,0x00, //..%@+.@@.... +0x03,0xea,0x08,0xc5,0x00,0x00, //..@%.+%+.... +0x08,0xa0,0x0a,0x50,0x00,0x00, //.+%..%+..... + + +/* # */ +0x00,0x0c,0xa0,0x00,0xac,0x00, //...%%...%%.. +0x00,0x0a,0x80,0x00,0xac,0x00, //...%+...%%.. +0x00,0x0c,0x80,0x00,0xca,0x00, //...%+...%%.. +0x03,0x3c,0x83,0x33,0xca,0x30, //...%+...%%.. +0x8e,0xff,0xff,0xff,0xff,0xe8, //+@@@@@@@@@@+ +0x5a,0xac,0xca,0xaa,0xec,0xa5, //+%%%%%%%@%%+ +0x00,0x5a,0x30,0x00,0xa5,0x00, //..+%....%+.. +0x00,0x5a,0x30,0x03,0xa5,0x00, //..+%....%+.. +0x00,0x8c,0x00,0x05,0xa3,0x00, //..+%...+%... +0x00,0x8c,0x00,0x05,0xa3,0x00, //..+%...+%... +0x8c,0xee,0xcc,0xce,0xfc,0xc8, //+%@@%%%@@%%+ +0x8e,0xff,0xff,0xff,0xff,0xe8, //+@@@@@@@@@@+ +0x00,0xca,0x00,0x0a,0xc0,0x00, //..%%...%%... +0x00,0xca,0x00,0x0a,0xc0,0x00, //..%%...%%... +0x00,0xa8,0x00,0x0a,0xc0,0x00, //..%+...%%... +0x00,0xc8,0x00,0x0c,0xa0,0x00, //..%+...%%... + + +/* $ */ +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x03,0xcf,0xfe,0xa0,0x00, //....%@@@%... +0x00,0x5e,0xca,0xc8,0xec,0x00, //..+@%%%+@%.. +0x00,0xee,0x0a,0xc3,0xee,0x30, //..@@.%%.@@.. +0x03,0xec,0x0a,0xc8,0xec,0x00, //..@%.%%+@%.. +0x03,0xee,0x3a,0xc0,0x00,0x00, //..@@.%%..... +0x00,0xaf,0xea,0xc0,0x00,0x00, //..%@@%%..... +0x00,0x0c,0xff,0xc0,0x00,0x00, //...%@@%..... +0x00,0x00,0xae,0xfc,0x00,0x00, //....%@@%.... +0x00,0x00,0x0a,0xff,0xc0,0x00, //.....%@@%... +0x00,0x00,0x0a,0xce,0xfa,0x00, //.....%%@@%.. +0x00,0x00,0x0a,0xc3,0xee,0x30, //.....%%.@@.. +0x05,0xee,0x0a,0xc0,0xae,0x50, //.+@@.%%.%@+. +0x0a,0xfe,0x3a,0xc0,0xae,0x50, //.%@@.%%.%@+. +0x08,0xea,0x0a,0xc0,0xce,0x30, //.+@%.%%.%@.. +0x00,0xee,0x5a,0xc8,0xc8,0x00, //..@@+%%+%+.. +0x00,0x0a,0xef,0xfc,0x50,0x00, //...%@@@%+... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x03,0x50,0x00,0x00, //......+..... + + +/* % */ +0x0a,0xee,0x50,0x00,0xaa,0x00, //.%@@+...%%.. +0x8c,0x5a,0xe3,0x03,0x83,0x00, //+%+%@...+... +0xce,0x05,0xc8,0x0a,0xa0,0x00, //%@.+%+.%%... +0xec,0x03,0xea,0x0a,0x50,0x00, //@%..@%.%+... +0xec,0x03,0xea,0x8a,0x00,0x00, //@%..@%+%.... +0xec,0x03,0xea,0xc8,0x00,0x00, //@%..@%%+.... +0xce,0x05,0xc8,0xa3,0x00,0x00, //%@.+%+%..... +0x8c,0x5a,0xea,0xaa,0xee,0x80, //+%+%@%%%@@+. +0x0a,0xee,0x8a,0x6c,0x8a,0xe3, //.%@@+%+%+%@. +0x00,0x00,0x8a,0xae,0x05,0xc8, //....+%%@.+%+ +0x00,0x00,0xa5,0xec,0x03,0xea, //....%+@%..@% +0x00,0x05,0xa0,0xec,0x03,0xea, //...+%.@%..@% +0x00,0x0a,0x80,0xec,0x03,0xea, //...%+.@%..@% +0x00,0x38,0x30,0xce,0x05,0xc8, //...+..%@.+%+ +0x00,0xaa,0x00,0x5a,0x5a,0xe3, //..%%..+%+%@. +0x03,0xa5,0x00,0x0a,0xee,0x80, //..%+...%@@+. + + +/* & */ +0x00,0x3c,0xfe,0xa0,0x00,0x00, //...%@@%..... +0x00,0xce,0x38,0xc8,0x00,0x00, //..%@.+%+.... +0x03,0xea,0x05,0xea,0x00,0x00, //..@%.+@%.... +0x05,0xc8,0x05,0xea,0x00,0x00, //.+%+.+@%.... +0x03,0xea,0x08,0xc5,0x00,0x00, //..@%.+%+.... +0x03,0xec,0x0c,0xc0,0x00,0x00, //..@%.%%..... +0x00,0xce,0xaa,0x00,0x00,0x00, //..%@%%...... +0x00,0xcf,0xa0,0x5e,0xff,0xc0, //..%@%.+@@@%. +0x0c,0xae,0xe0,0x03,0xea,0x00, //.%%@@...@%.. +0x8c,0x3c,0xe8,0x03,0xa5,0x00, //+%.%@+..%+.. +0xce,0x05,0xee,0x05,0xa0,0x00, //%@.+@@.+%... +0xee,0x00,0xaf,0xaa,0xa0,0x00, //@@..%@%%%... +0xee,0x30,0x3e,0xea,0x50,0x00, //@@...@@%+... +0xce,0x50,0x05,0xee,0x30,0x33, //%@+..+@@.... +0x3e,0xe5,0x08,0xce,0xe3,0xaa, //.@@+.+%@@.%% +0x03,0xcf,0xec,0x35,0xef,0xc3, //..%@@%.+@@%. + + +/* ' */ +0x08,0xee,0x50,0x00,0x00,0x00, //.+@@+....... +0x0a,0xff,0xa0,0x00,0x00,0x00, //.%@@%....... +0x00,0xae,0xa0,0x00,0x00,0x00, //..%@%....... +0x00,0x5c,0x80,0x00,0x00,0x00, //..+%+....... +0x00,0xcc,0x00,0x00,0x00,0x00, //..%%........ +0x0a,0xa0,0x00,0x00,0x00,0x00, //.%%......... + + +/* ( */ +0x00,0x00,0x00,0x00,0x0a,0xa0, //.........%%. +0x00,0x00,0x00,0x00,0x8c,0x30, //........+%.. +0x00,0x00,0x00,0x05,0xa5,0x00, //.......+%+.. +0x00,0x00,0x00,0x0e,0xc0,0x00, //.......@%... +0x00,0x00,0x00,0xae,0x30,0x00, //......%@.... +0x00,0x00,0x03,0xec,0x00,0x00, //......@%.... +0x00,0x00,0x08,0xc8,0x00,0x00, //.....+%+.... +0x00,0x00,0x0c,0xe3,0x00,0x00, //.....%@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xc0,0x00,0x00, //.....@%..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0c,0xe3,0x00,0x00, //.....%@..... +0x00,0x00,0x08,0xc8,0x00,0x00, //.....+%+.... +0x00,0x00,0x03,0xec,0x00,0x00, //......@%.... +0x00,0x00,0x00,0xae,0x30,0x00, //......%@.... +0x00,0x00,0x00,0x3e,0xa0,0x00, //.......@%... +0x00,0x00,0x00,0x05,0xa5,0x00, //.......+%+.. +0x00,0x00,0x00,0x00,0x8c,0x30, //........+%.. +0x00,0x00,0x00,0x00,0x0a,0xa0, //.........%%. + + +/* ) */ +0x0a,0x80,0x00,0x00,0x00,0x00, //.%+......... +0x03,0xc8,0x00,0x00,0x00,0x00, //..%+........ +0x00,0x8c,0x50,0x00,0x00,0x00, //..+%+....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x05,0xc8,0x00,0x00,0x00, //...+%+...... +0x00,0x00,0xce,0x00,0x00,0x00, //....%@...... +0x00,0x00,0x8c,0x80,0x00,0x00, //....+%+..... +0x00,0x00,0x5e,0xa0,0x00,0x00, //....+@%..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x5e,0xa0,0x00,0x00, //....+@%..... +0x00,0x00,0x8c,0x80,0x00,0x00, //....+%+..... +0x00,0x00,0xce,0x00,0x00,0x00, //....%@...... +0x00,0x05,0xea,0x00,0x00,0x00, //...+@%...... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x8c,0x50,0x00,0x00,0x00, //..+%+....... +0x03,0xc8,0x00,0x00,0x00,0x00, //..%+........ +0x0a,0x80,0x00,0x00,0x00,0x00, //.%+......... + + +/* * */ +0x00,0x00,0x3e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x3e,0xe5,0x0e,0xc0,0x8e,0xe0, //.@@+.@%.+@@. +0x0a,0xee,0x5c,0xaa,0xfe,0xa0, //.%@@+%%%@@%. +0x00,0x05,0xa8,0xaa,0x50,0x00, //...+%+%%+... +0x00,0x05,0xaa,0xaa,0x50,0x00, //...+%%%%+... +0x0a,0xee,0xaa,0xaa,0xfe,0xa0, //.%@@%%%%@@%. +0x5e,0xe5,0x0e,0xc0,0x8e,0xe3, //+@@+.@%.+@@. +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x5e,0xe3,0x00,0x00, //....+@@..... +0x00,0x00,0x5e,0xe0,0x00,0x00, //....+@@..... + + +/* + */ +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x3e,0xff,0xff,0xff,0xff,0xe5, //.@@@@@@@@@@+ +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x0a,0xc0,0x00,0x00, //.....%%..... + + +/* , */ +0x08,0xee,0x50,0x00,0x00,0x00, //.+@@+....... +0x0a,0xff,0xa0,0x00,0x00,0x00, //.%@@%....... +0x00,0xaf,0xa0,0x00,0x00,0x00, //..%@%....... +0x00,0x5c,0x80,0x00,0x00,0x00, //..+%+....... +0x00,0xcc,0x00,0x00,0x00,0x00, //..%%........ +0x0a,0xa0,0x00,0x00,0x00,0x00, //.%%......... + + +/* - */ +0xaf,0xff,0xff,0xff,0xff,0xe0, //%@@@@@@@@@@. + + +/* . */ +0x08,0xee,0x30,0x00,0x00,0x00, //.+@@........ +0x0c,0xfe,0x80,0x00,0x00,0x00, //.%@@+....... +0x08,0xee,0x30,0x00,0x00,0x00, //.+@@........ + + +/* / */ +0x00,0x00,0x00,0x00,0x03,0x83, //..........+. +0x00,0x00,0x00,0x00,0x0a,0xc0, //.........%%. +0x00,0x00,0x00,0x00,0x3a,0x50, //.........%+. +0x00,0x00,0x00,0x00,0xac,0x00, //........%%.. +0x00,0x00,0x00,0x03,0xa5,0x00, //........%+.. +0x00,0x00,0x00,0x08,0xc0,0x00, //.......+%... +0x00,0x00,0x00,0x0a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x8c,0x00,0x00, //......+%.... +0x00,0x00,0x00,0xa5,0x00,0x00, //......%+.... +0x00,0x00,0x08,0xc0,0x00,0x00, //.....+%..... +0x00,0x00,0x0c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x8c,0x00,0x00,0x00, //....+%...... +0x00,0x00,0xc8,0x00,0x00,0x00, //....%+...... +0x00,0x08,0xc0,0x00,0x00,0x00, //...+%....... +0x00,0x0a,0x80,0x00,0x00,0x00, //...%+....... +0x00,0x8c,0x00,0x00,0x00,0x00, //..+%........ +0x00,0xc8,0x00,0x00,0x00,0x00, //..%+........ +0x08,0xa0,0x00,0x00,0x00,0x00, //.+%......... +0x0c,0x80,0x00,0x00,0x00,0x00, //.%+......... +0x5a,0x00,0x00,0x00,0x00,0x00, //+%.......... + + +/* 0 */ +0x00,0x05,0xcf,0xfc,0x30,0x00, //...+%@@%.... +0x00,0x5e,0xe3,0x3e,0xe5,0x00, //..+@@..@@+.. +0x00,0xee,0x50,0x03,0xee,0x00, //..@@+...@@.. +0x08,0xec,0x00,0x00,0xce,0x50, //.+@%....%@+. +0x0c,0xe8,0x00,0x00,0xaf,0xa0, //.%@+....%@%. +0x0e,0xe5,0x00,0x00,0x8e,0xc0, //.@@+....+@%. +0x3e,0xe3,0x00,0x00,0x5e,0xe0, //.@@.....+@@. +0x3e,0xe3,0x00,0x00,0x5e,0xe0, //.@@.....+@@. +0x3e,0xe3,0x00,0x00,0x5e,0xe0, //.@@.....+@@. +0x3e,0xe3,0x00,0x00,0x5e,0xe0, //.@@.....+@@. +0x0e,0xe5,0x00,0x00,0x8e,0xc0, //.@@+....+@%. +0x0c,0xe8,0x00,0x00,0xaf,0xa0, //.%@+....%@%. +0x08,0xec,0x00,0x00,0xce,0x50, //.+@%....%@+. +0x00,0xee,0x50,0x05,0xec,0x00, //..@@+..+@%.. +0x00,0x5e,0xe3,0x3e,0xe3,0x00, //..+@@..@@... +0x00,0x05,0xcf,0xfc,0x30,0x00, //...+%@@%.... + + +/* 1 */ +0x00,0x00,0x03,0x83,0x00,0x00, //......+..... +0x00,0x5a,0xcf,0xe3,0x00,0x00, //..+%%@@..... +0x00,0x36,0x8e,0xe3,0x00,0x00, //...++@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x5e,0xe8,0x00,0x00, //....+@@+.... +0x00,0x8e,0xff,0xff,0xfc,0x00, //..+@@@@@@%.. + + +/* 2 */ +0x00,0x0a,0xef,0xfe,0xa0,0x00, //...%@@@@%... +0x00,0xcc,0x50,0x0a,0xee,0x00, //..%%+..%@@.. +0x0a,0xe5,0x00,0x00,0xce,0x80, //.%@+....%@+. +0x0c,0xe5,0x00,0x00,0x8e,0xa0, //.%@+....+@%. +0x0c,0xfc,0x00,0x00,0x8e,0xa0, //.%@%....+@%. +0x03,0x63,0x00,0x00,0xae,0x80, //..+.....%@+. +0x00,0x00,0x00,0x03,0xee,0x00, //........@@.. +0x00,0x00,0x00,0x0a,0xe3,0x00, //.......%@... +0x00,0x00,0x00,0x8c,0x30,0x00, //......+%.... +0x00,0x00,0x08,0xc3,0x00,0x00, //.....+%..... +0x00,0x00,0x8c,0x30,0x00,0x00, //....+%...... +0x00,0x08,0xc3,0x00,0x00,0x00, //...+%....... +0x00,0x8c,0x30,0x00,0x08,0xa0, //..+%.....+%. +0x05,0xa5,0x00,0x00,0x0c,0xa0, //.+%+.....%%. +0x3e,0xc6,0x66,0x66,0xce,0x80, //.@%+++++%@+. +0x3e,0xff,0xff,0xff,0xfe,0x50, //.@@@@@@@@@+. + + +/* 3 */ +0x00,0x3a,0xef,0xfc,0x50,0x00, //...%@@@%+... +0x00,0xcc,0x30,0x5e,0xe5,0x00, //..%%..+@@+.. +0x08,0xc8,0x00,0x05,0xee,0x00, //.+%+...+@@.. +0x08,0xec,0x00,0x00,0xee,0x30, //.+@%....@@.. +0x00,0x53,0x00,0x00,0xee,0x00, //..+.....@@.. +0x00,0x00,0x00,0x05,0xea,0x00, //.......+@%.. +0x00,0x00,0x00,0x5c,0xa0,0x00, //......+%%... +0x00,0x00,0xaf,0xfc,0x30,0x00, //....%@@%.... +0x00,0x00,0x00,0x3c,0xe8,0x00, //.......%@+.. +0x00,0x00,0x00,0x00,0xee,0x30, //........@@.. +0x00,0x00,0x00,0x00,0x8e,0xa0, //........+@%. +0x00,0x53,0x00,0x00,0x8e,0xc0, //..+.....+@%. +0x0c,0xfc,0x00,0x00,0x8e,0xa0, //.%@%....+@%. +0x0c,0xfa,0x00,0x00,0xce,0x50, //.%@%....%@+. +0x03,0xec,0x30,0x3c,0xfa,0x00, //..@%...%@%.. +0x00,0x3c,0xef,0xfc,0x50,0x00, //...%@@@%+... + + +/* 4 */ +0x00,0x00,0x00,0x0e,0xc0,0x00, //.......@%... +0x00,0x00,0x00,0xaf,0xc0,0x00, //......%@%... +0x00,0x00,0x05,0xef,0xc0,0x00, //.....+@@%... +0x00,0x00,0x0e,0xce,0xc0,0x00, //.....@%@%... +0x00,0x00,0xce,0x5e,0xc0,0x00, //....%@+@%... +0x00,0x08,0xc5,0x5e,0xc0,0x00, //...+%++@%... +0x00,0x3c,0x80,0x5e,0xc0,0x00, //...%+.+@%... +0x00,0xcc,0x00,0x5e,0xc0,0x00, //..%%..+@%... +0x08,0xc0,0x00,0x5e,0xc0,0x00, //.+%...+@%... +0x3a,0x50,0x00,0x5e,0xc0,0x00, //.%+...+@%... +0x8e,0xff,0xff,0xff,0xff,0xe5, //+@@@@@@@@@@+ +0x00,0x00,0x00,0x5e,0xc0,0x00, //......+@%... +0x00,0x00,0x00,0x5e,0xc0,0x00, //......+@%... +0x00,0x00,0x00,0x5e,0xc0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xe3,0x00, //......+@@... +0x00,0x00,0xaf,0xff,0xff,0xe0, //....%@@@@@@. + + +/* 5 */ +0x00,0xcf,0xff,0xff,0xfe,0x80, //..%@@@@@@@+. +0x00,0xaa,0x66,0x66,0x65,0x30, //..%%++++++.. +0x00,0xa8,0x00,0x00,0x00,0x00, //..%+........ +0x00,0xc8,0x00,0x00,0x00,0x00, //..%+........ +0x00,0xa5,0x00,0x00,0x00,0x00, //..%+........ +0x00,0xa5,0x00,0x00,0x00,0x00, //..%+........ +0x03,0xa5,0xcf,0xfe,0xa0,0x00, //..%+%@@@%... +0x03,0xaa,0x80,0x08,0xec,0x00, //..%%+..+@%.. +0x00,0xa8,0x00,0x00,0xce,0x50, //..%+....%@+. +0x00,0x00,0x00,0x00,0x8e,0xa0, //........+@%. +0x00,0x00,0x00,0x00,0x5e,0xc0, //........+@%. +0x08,0xca,0x00,0x00,0x5e,0xc0, //.+%%....+@%. +0x0c,0xfc,0x00,0x00,0x8e,0xa0, //.%@%....+@%. +0x0a,0xe5,0x00,0x00,0xce,0x50, //.%@+....%@+. +0x03,0xec,0x30,0x3c,0xfa,0x00, //..@%...%@%.. +0x00,0x3a,0xef,0xfe,0x80,0x00, //...%@@@@+... + + +/* 6 */ +0x00,0x00,0xae,0xff,0xc3,0x00, //....%@@@%... +0x00,0x0c,0xe5,0x05,0xee,0x00, //...%@+.+@@.. +0x00,0xce,0x30,0x05,0xee,0x30, //..%@...+@@.. +0x05,0xea,0x00,0x00,0x33,0x00, //.+@%........ +0x0a,0xe8,0x00,0x00,0x00,0x00, //.%@+........ +0x0e,0xe5,0x00,0x00,0x00,0x00, //.@@+........ +0x0e,0xe3,0xae,0xff,0xc3,0x00, //.@@.%@@@%... +0x3e,0xec,0xc3,0x05,0xee,0x30, //.@@%%..+@@.. +0x3e,0xfc,0x00,0x00,0x8e,0xa0, //.@@%....+@%. +0x3e,0xe3,0x00,0x00,0x3e,0xe0, //.@@......@@. +0x3e,0xe3,0x00,0x00,0x3e,0xe0, //.@@......@@. +0x0e,0xe5,0x00,0x00,0x3e,0xe0, //.@@+.....@@. +0x0a,0xfa,0x00,0x00,0x3e,0xc0, //.%@%.....@%. +0x05,0xee,0x30,0x00,0x8c,0x80, //.+@@....+%+. +0x00,0xae,0xe3,0x05,0xec,0x00, //..%@@..+@%.. +0x00,0x05,0xcf,0xfe,0xa0,0x00, //...+%@@@%... + + +/* 7 */ +0x05,0xef,0xff,0xff,0xff,0xe0, //.+@@@@@@@@@. +0x08,0xec,0x66,0x66,0x8c,0x80, //.+@%+++++%+. +0x0a,0xc0,0x00,0x00,0xac,0x00, //.%%.....%%.. +0x0a,0x80,0x00,0x03,0xa5,0x00, //.%+.....%+.. +0x00,0x00,0x00,0x0a,0xa0,0x00, //.......%%... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0xac,0x00,0x00, //......%%.... +0x00,0x00,0x03,0xc8,0x00,0x00, //......%+.... +0x00,0x00,0x0a,0xe3,0x00,0x00, //.....%@..... +0x00,0x00,0x0e,0xc0,0x00,0x00, //.....@%..... +0x00,0x00,0x5e,0xa0,0x00,0x00, //....+@%..... +0x00,0x00,0xae,0x80,0x00,0x00, //....%@+..... +0x00,0x00,0xce,0x80,0x00,0x00, //....%@+..... +0x00,0x00,0xef,0xa0,0x00,0x00, //....@@%..... +0x00,0x03,0xef,0xa0,0x00,0x00, //....@@%..... +0x00,0x00,0xce,0x80,0x00,0x00, //....%@+..... + + +/* 8 */ +0x00,0x3a,0xef,0xfe,0xa0,0x00, //...%@@@@%... +0x00,0xee,0x50,0x08,0xec,0x00, //..@@+..+@%.. +0x0a,0xe5,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0c,0xe0,0x00,0x00,0x5e,0xa0, //.%@.....+@%. +0x0c,0xe3,0x00,0x00,0x5c,0x80, //.%@.....+%+. +0x08,0xee,0x30,0x00,0xae,0x30, //.+@@....%@.. +0x00,0xae,0xe8,0x05,0xa5,0x00, //..%@@+.+%+.. +0x00,0x08,0xef,0xfe,0x30,0x00, //...+@@@@.... +0x00,0xac,0x35,0xcf,0xe3,0x00, //..%%.+%@@... +0x08,0xc5,0x00,0x0a,0xee,0x30, //.+%+...%@@.. +0x0e,0xc0,0x00,0x00,0xaf,0xa0, //.@%.....%@%. +0x3e,0xa0,0x00,0x00,0x3e,0xc0, //.@%......@%. +0x3e,0xa0,0x00,0x00,0x3e,0xc0, //.@%......@%. +0x0e,0xe3,0x00,0x00,0x8c,0x80, //.@@.....+%+. +0x03,0xee,0x50,0x08,0xec,0x00, //..@@+..+@%.. +0x00,0x3a,0xef,0xfe,0x80,0x00, //...%@@@@+... + + +/* 9 */ +0x00,0x3a,0xef,0xfc,0x50,0x00, //...%@@@%+... +0x00,0xee,0x50,0x3c,0xe8,0x00, //..@@+..%@+.. +0x0a,0xe8,0x00,0x00,0xee,0x30, //.%@+....@@.. +0x0e,0xe3,0x00,0x00,0xae,0x80, //.@@.....%@+. +0x3e,0xe0,0x00,0x00,0x8e,0xc0, //.@@.....+@%. +0x3e,0xe0,0x00,0x00,0x8e,0xc0, //.@@.....+@%. +0x3e,0xe0,0x00,0x00,0xaf,0xe0, //.@@.....%@@. +0x0e,0xe5,0x00,0x03,0xef,0xe0, //.@@+....@@@. +0x08,0xee,0x50,0x5c,0x8e,0xe0, //.+@@+.+%+@@. +0x00,0x5c,0xff,0xe8,0xaf,0xc0, //..+%@@@+%@%. +0x00,0x00,0x00,0x00,0xcf,0xa0, //........%@%. +0x00,0x00,0x00,0x00,0xee,0x50, //........@@+. +0x00,0x30,0x00,0x05,0xee,0x00, //.......+@@.. +0x05,0xee,0x30,0x0c,0xe8,0x00, //.+@@...%@+.. +0x05,0xee,0x33,0xcf,0xa0,0x00, //.+@@..%@%... +0x00,0x5e,0xff,0xe5,0x00,0x00, //..+@@@@+.... + + +/* : */ +0x00,0x00,0xae,0xc0,0x00,0x00, //....%@%..... +0x00,0x00,0xef,0xe3,0x00,0x00, //....@@@..... +0x00,0x00,0xae,0xc0,0x00,0x00, //....%@%..... +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,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,0xc0,0x00,0x00, //....%@%..... +0x00,0x00,0xef,0xe3,0x00,0x00, //....@@@..... +0x00,0x00,0xae,0xc0,0x00,0x00, //....%@%..... + + +/* ; */ +0x00,0x00,0x8e,0xe3,0x00,0x00, //....+@@..... +0x00,0x00,0x8c,0xc3,0x00,0x00, //....+%%..... +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x8c,0xc3,0x00,0x00, //....+%%..... +0x00,0x00,0x8e,0xe3,0x00,0x00, //....+@@..... +0x00,0x00,0x0c,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x5a,0x50,0x00,0x00, //....+%+..... + + +/* < */ +0x00,0x00,0x00,0x00,0x5a,0x30, //........+%.. +0x00,0x00,0x00,0x05,0xa5,0x00, //.......+%+.. +0x00,0x00,0x00,0x5a,0x50,0x00, //......+%+... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x5a,0x50,0x00,0x00, //....+%+..... +0x00,0x05,0xa5,0x00,0x00,0x00, //...+%+...... +0x00,0x5a,0x50,0x00,0x00,0x00, //..+%+....... +0x05,0xa5,0x00,0x00,0x00,0x00, //.+%+........ +0x05,0xa5,0x00,0x00,0x00,0x00, //.+%+........ +0x00,0x5a,0x50,0x00,0x00,0x00, //..+%+....... +0x00,0x05,0xa5,0x00,0x00,0x00, //...+%+...... +0x00,0x00,0x5a,0x50,0x00,0x00, //....+%+..... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x00,0x5a,0x50,0x00, //......+%+... +0x00,0x00,0x00,0x05,0xa5,0x00, //.......+%+.. +0x00,0x00,0x00,0x00,0x5a,0x30, //........+%.. + + +/* = */ +0xaf,0xff,0xff,0xff,0xff,0xe0, //%@@@@@@@@@@. +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0xaf,0xff,0xff,0xff,0xff,0xe0, //%@@@@@@@@@@. + + +/* > */ +0x0a,0xc0,0x00,0x00,0x00,0x00, //.%%......... +0x00,0xcc,0x00,0x00,0x00,0x00, //..%%........ +0x00,0x0c,0xc0,0x00,0x00,0x00, //...%%....... +0x00,0x00,0xcc,0x00,0x00,0x00, //....%%...... +0x00,0x00,0x0c,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0x00,0xcc,0x00,0x00, //......%%.... +0x00,0x00,0x00,0x0c,0xc0,0x00, //.......%%... +0x00,0x00,0x00,0x00,0xcc,0x00, //........%%.. +0x00,0x00,0x00,0x00,0xcc,0x00, //........%%.. +0x00,0x00,0x00,0x0c,0xc0,0x00, //.......%%... +0x00,0x00,0x00,0xcc,0x00,0x00, //......%%.... +0x00,0x00,0x0c,0xc0,0x00,0x00, //.....%%..... +0x00,0x00,0xcc,0x00,0x00,0x00, //....%%...... +0x00,0x0c,0xc0,0x00,0x00,0x00, //...%%....... +0x00,0xcc,0x00,0x00,0x00,0x00, //..%%........ +0x0a,0xc0,0x00,0x00,0x00,0x00, //.%%......... + + +/* ? */ +0x00,0x08,0xef,0xfe,0xa3,0x00, //...+@@@@%... +0x00,0xcc,0x30,0x05,0xee,0x30, //..%%...+@@.. +0x0a,0xc0,0x00,0x00,0x8e,0xc0, //.%%.....+@%. +0x0e,0xa0,0x00,0x00,0x5e,0xe0, //.@%.....+@@. +0x0e,0xea,0x00,0x00,0x5e,0xe0, //.@@%....+@@. +0x0c,0xfc,0x00,0x00,0xaf,0xa0, //.%@%....%@%. +0x00,0x00,0x00,0x0a,0xca,0x00, //.......%%%.. +0x00,0x00,0x03,0xec,0x50,0x00, //......@%+... +0x00,0x00,0x0c,0xa0,0x00,0x00, //.....%%..... +0x00,0x00,0x0c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x0c,0x80,0x00,0x00, //.....%+..... +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... +0x00,0x00,0xcf,0xe5,0x00,0x00, //....%@@+.... +0x00,0x00,0x8e,0xc0,0x00,0x00, //....+@%..... + + +/* @ */ +0x00,0x00,0xae,0xff,0xc3,0x00, //....%@@@%... +0x00,0x3e,0xe5,0x03,0xac,0x50, //...@@+..%%+. +0x00,0xcc,0x30,0x00,0x0a,0xc0, //..%%.....%%. +0x08,0xc5,0x05,0xee,0xea,0xc8, //.+%+.+@@@%%+ +0x0c,0xe0,0x3e,0xc5,0xc8,0xca, //.%@..@%+%+%% +0x3e,0xc0,0xce,0x05,0xa5,0xaa, //.@%.%@.+%+%% +0x3e,0xa3,0xea,0x08,0xc3,0xac, //.@%.@%.+%.%% +0x5e,0xa8,0xc5,0x0a,0xe0,0xaa, //+@%+%+.%@.%% +0x5e,0xaa,0xe3,0x0c,0xe0,0xca, //+@%%@..%@.%% +0x5e,0xac,0xe3,0x3e,0xc3,0xa5, //+@%%@..@%.%+ +0x3e,0xaa,0xe3,0xcf,0xaa,0xc0, //.@%%@.%@%%%. +0x0c,0xe0,0xcf,0xca,0xec,0x30, //.%@.%@%%@%.. +0x08,0xc5,0x00,0x00,0x00,0xa8, //.+%+......%+ +0x00,0xec,0x00,0x00,0x0a,0xc0, //..@%.....%%. +0x00,0x5e,0xc3,0x03,0xcc,0x30, //..+@%...%%.. +0x00,0x03,0xcf,0xfe,0xa3,0x00, //....%@@@%... + + +/* A */ +0x00,0x00,0x08,0xa0,0x00,0x00, //.....+%..... +0x00,0x00,0x5e,0xe5,0x00,0x00, //....+@@+.... +0x00,0x00,0xae,0xe8,0x00,0x00, //....%@@+.... +0x00,0x00,0xca,0xec,0x00,0x00, //....%%@%.... +0x00,0x03,0xa5,0xee,0x00,0x00, //....%+@@.... +0x00,0x08,0xc0,0xee,0x50,0x00, //...+%.@@+... +0x00,0x0a,0xc0,0xae,0x80,0x00, //...%%.%@+... +0x00,0x0c,0x80,0x5e,0xc0,0x00, //...%+.+@%... +0x00,0x3a,0x50,0x3e,0xe0,0x00, //...%+..@@... +0x00,0x8c,0x00,0x0c,0xe5,0x00, //..+%...%@+.. +0x00,0xcf,0xff,0xff,0xfa,0x00, //..%@@@@@@%.. +0x00,0xc8,0x00,0x08,0xec,0x00, //..%+...+@%.. +0x05,0xa3,0x00,0x03,0xee,0x30, //.+%.....@@.. +0x0a,0xc0,0x00,0x00,0xce,0x50, //.%%.....%@+. +0x0e,0xc0,0x00,0x00,0xaf,0xa0, //.@%.....%@%. +0xef,0xfc,0x00,0x0a,0xff,0xfc, //@@@%...%@@@% + + +/* B */ +0xaf,0xff,0xff,0xfe,0xc5,0x00, //%@@@@@@@%+.. +0x05,0xec,0x00,0x08,0xee,0x50, //.+@%...+@@+. +0x05,0xec,0x00,0x00,0x8e,0xa0, //.+@%....+@%. +0x05,0xec,0x00,0x00,0x8e,0xa0, //.+@%....+@%. +0x05,0xec,0x00,0x00,0xae,0x80, //.+@%....%@+. +0x05,0xec,0x00,0x0a,0xca,0x00, //.+@%...%%%.. +0x05,0xef,0xff,0xfe,0x80,0x00, //.+@@@@@@+... +0x05,0xec,0x00,0x05,0xec,0x30, //.+@%...+@%.. +0x05,0xec,0x00,0x00,0x5e,0xc0, //.+@%....+@%. +0x05,0xec,0x00,0x00,0x0e,0xe5, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x0c,0xe8, //.+@%.....%@+ +0x05,0xec,0x00,0x00,0x0e,0xe5, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x5e,0xe3, //.+@%....+@@. +0x05,0xec,0x00,0x05,0xee,0x80, //.+@%...+@@+. +0xcf,0xff,0xff,0xfe,0xc5,0x00, //%@@@@@@@%+.. + + +/* C */ +0x00,0x03,0xae,0xff,0xea,0xa0, //....%@@@@%%. +0x00,0x5e,0xe5,0x03,0xae,0xe0, //..+@@+..%@@. +0x03,0xee,0x30,0x00,0x0a,0xe3, //..@@.....%@. +0x0a,0xfa,0x00,0x00,0x03,0xa5, //.%@%......%+ +0x3e,0xe3,0x00,0x00,0x00,0x53, //.@@.......+. +0x5e,0xe0,0x00,0x00,0x00,0x00, //+@@......... +0x8e,0xc0,0x00,0x00,0x00,0x00, //+@%......... +0x8e,0xc0,0x00,0x00,0x00,0x00, //+@%......... +0x8e,0xc0,0x00,0x00,0x00,0x00, //+@%......... +0x5e,0xe0,0x00,0x00,0x00,0x00, //+@@......... +0x3e,0xe3,0x00,0x00,0x00,0x33, //.@@......... +0x0e,0xe8,0x00,0x00,0x00,0x85, //.@@+......++ +0x08,0xec,0x00,0x00,0x0a,0xc0, //.+@%.....%%. +0x00,0xaf,0xc3,0x03,0xac,0x30, //..%@%...%%.. +0x00,0x05,0xcf,0xfe,0xa3,0x00, //...+%@@@%... + + +/* D */ +0xaf,0xff,0xff,0xea,0x30,0x00, //%@@@@@@%.... +0x05,0xec,0x00,0x5e,0xe8,0x00, //.+@%..+@@+.. +0x05,0xec,0x00,0x03,0xee,0x50, //.+@%....@@+. +0x05,0xec,0x00,0x00,0x8e,0xc0, //.+@%....+@%. +0x05,0xec,0x00,0x00,0x3e,0xe3, //.+@%.....@@. +0x05,0xec,0x00,0x00,0x0e,0xe5, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x0e,0xe8, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x0c,0xe8, //.+@%.....%@+ +0x05,0xec,0x00,0x00,0x0e,0xe5, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x0e,0xe5, //.+@%.....@@+ +0x05,0xec,0x00,0x00,0x3e,0xe0, //.+@%.....@@. +0x05,0xec,0x00,0x00,0x8e,0xc0, //.+@%....+@%. +0x05,0xec,0x00,0x03,0xee,0x30, //.+@%....@@.. +0x05,0xec,0x00,0x8e,0xe5,0x00, //.+@%..+@@+.. +0xcf,0xff,0xff,0xea,0x30,0x00, //%@@@@@@%.... + + +/* E */ +0x8e,0xff,0xff,0xff,0xfe,0x80, //+@@@@@@@@@+. +0x03,0xee,0x00,0x00,0xae,0xc0, //..@@....%@%. +0x03,0xee,0x00,0x00,0x08,0xc0, //..@@.....+%. +0x03,0xee,0x00,0x00,0x30,0x53, //..@@......+. +0x03,0xee,0x00,0x03,0x80,0x00, //..@@....+... +0x03,0xee,0x00,0x0a,0xe0,0x00, //..@@...%@... +0x03,0xef,0xff,0xff,0xe0,0x00, //..@@@@@@@... +0x03,0xee,0x00,0x0a,0xe0,0x00, //..@@...%@... +0x03,0xee,0x00,0x05,0xa0,0x00, //..@@...+%... +0x03,0xee,0x00,0x00,0x30,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x88, //..@@......++ +0x03,0xee,0x00,0x00,0x05,0xa3, //..@@.....+%. +0x03,0xee,0x00,0x00,0x8e,0xe0, //..@@....+@@. +0x8e,0xff,0xff,0xff,0xff,0xa0, //+@@@@@@@@@%. + + +/* F */ +0x8e,0xff,0xff,0xff,0xff,0xc0, //+@@@@@@@@@%. +0x03,0xee,0x00,0x00,0x5e,0xe3, //..@@....+@@. +0x03,0xee,0x00,0x00,0x03,0xc8, //..@@......%+ +0x03,0xee,0x00,0x00,0x00,0x88, //..@@......++ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x85,0x00, //..@@....++.. +0x03,0xee,0x00,0x05,0xa5,0x00, //..@@...+%+.. +0x03,0xef,0xff,0xff,0xe5,0x00, //..@@@@@@@+.. +0x03,0xee,0x00,0x05,0xa5,0x00, //..@@...+%+.. +0x03,0xee,0x00,0x00,0xa5,0x00, //..@@....%+.. +0x03,0xee,0x00,0x00,0x53,0x00, //..@@....+... +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0xaf,0xff,0xe5,0x00,0x00,0x00, //%@@@@+...... + + +/* G */ +0x00,0x05,0xcf,0xfc,0x88,0x00, //...+%@@%++.. +0x00,0x8e,0xc3,0x08,0xee,0x00, //..+@%..+@@.. +0x05,0xee,0x00,0x00,0xae,0x30, //.+@@....%@.. +0x0c,0xe5,0x00,0x00,0x3a,0x50, //.%@+.....%+. +0x3e,0xe0,0x00,0x00,0x05,0x30, //.@@......+.. +0x8e,0xc0,0x00,0x00,0x00,0x00, //+@%......... +0xaf,0xa0,0x00,0x00,0x00,0x00, //%@%......... +0xaf,0xa0,0x00,0x00,0x00,0x00, //%@%......... +0xaf,0xa0,0x00,0x5a,0xaa,0xa8, //%@%...+%%%%+ +0x8e,0xc0,0x00,0x38,0xef,0xc5, //+@%....+@@%+ +0x5e,0xe0,0x00,0x00,0xce,0x50, //+@@.....%@+. +0x0e,0xe5,0x00,0x00,0xce,0x50, //.@@+....%@+. +0x08,0xec,0x00,0x00,0xce,0x50, //.+@%....%@+. +0x00,0xcf,0xa0,0x05,0xee,0x50, //..%@%..+@@+. +0x00,0x08,0xef,0xfe,0x80,0x00, //...+@@@@+... + + +/* H */ +0xaf,0xff,0xa0,0x0c,0xff,0xfa, //%@@@%..%@@@% +0x0a,0xfa,0x00,0x00,0xae,0x80, //.%@%....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xff,0xff,0xff,0xfe,0x80, //.%@@@@@@@@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0x0a,0xe8,0x00,0x00,0xae,0x80, //.%@+....%@+. +0xcf,0xff,0xc0,0x0c,0xff,0xfc, //%@@@%..%@@@% + + +/* I */ +0x00,0xcf,0xff,0xff,0xfe,0x00, //..%@@@@@@@.. +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0xcf,0xff,0xff,0xfe,0x00, //..%@@@@@@@.. + + +/* J */ +0x00,0x08,0xef,0xff,0xff,0xfa, //...+@@@@@@@% +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x00,0x00,0x00,0x8e,0xa0,0x00, //......+@%... +0x5e,0xe0,0x00,0xce,0x50,0x00, //+@@...%@+... +0x8e,0xe0,0x08,0xec,0x00,0x00, //+@@..+@%.... +0x0a,0xef,0xfc,0x80,0x00,0x00, //.%@@@%+..... + + +/* K */ +0xaf,0xff,0xe3,0x5e,0xff,0xe5, //%@@@@.+@@@@+ +0x05,0xec,0x00,0x03,0xec,0x30, //.+@%....@%.. +0x05,0xec,0x00,0x0c,0xc0,0x00, //.+@%...%%... +0x05,0xec,0x00,0xcc,0x00,0x00, //.+@%..%%.... +0x05,0xec,0x0a,0xc3,0x00,0x00, //.+@%.%%..... +0x05,0xec,0x8c,0x50,0x00,0x00, //.+@%+%+..... +0x05,0xec,0xef,0xc0,0x00,0x00, //.+@%@@%..... +0x05,0xef,0xae,0xe5,0x00,0x00, //.+@@%@@+.... +0x05,0xee,0x08,0xec,0x00,0x00, //.+@@.+@%.... +0x05,0xec,0x00,0xce,0x80,0x00, //.+@%..%@+... +0x05,0xec,0x00,0x5e,0xe0,0x00, //.+@%..+@@... +0x05,0xec,0x00,0x0c,0xe8,0x00, //.+@%...%@+.. +0x05,0xec,0x00,0x03,0xee,0x00, //.+@%....@@.. +0x05,0xec,0x00,0x00,0xcf,0xa0, //.+@%....%@%. +0xaf,0xff,0xe3,0x0a,0xff,0xfc, //%@@@@..%@@@% + + +/* L */ +0x5e,0xff,0xfa,0x00,0x00,0x00, //+@@@@%...... +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0x00, //..@@........ +0x00,0xee,0x30,0x00,0x00,0xa8, //..@@......%+ +0x00,0xee,0x30,0x00,0x05,0xa5, //..@@.....+%+ +0x00,0xee,0x30,0x00,0x5e,0xe0, //..@@....+@@. +0x8e,0xff,0xff,0xff,0xff,0xc0, //+@@@@@@@@@%. + + +/* M */ +0xef,0xe5,0x00,0x00,0xcf,0xfe, //@@@+....%@@@ +0x0c,0xfa,0x00,0x00,0xef,0xc0, //.%@%....@@%. +0x0c,0xfc,0x00,0x05,0xef,0xc0, //.%@%...+@@%. +0x0a,0xee,0x00,0x08,0xce,0xc0, //.%@@...+%@%. +0x08,0xce,0x50,0x0c,0xce,0xc0, //.+%@+..%%@%. +0x08,0xae,0x80,0x0c,0x8e,0xc0, //.+%@+..%+@%. +0x08,0x6e,0xc0,0x5a,0x6e,0xc0, //.++@%.+%+@%. +0x08,0x5e,0xe0,0x8c,0x5e,0xc0, //.++@@.+%+@%. +0x08,0x5c,0xe3,0xaa,0x5e,0xc0, //.++%@.%%+@%. +0x08,0x5a,0xe8,0xc8,0x5e,0xc0, //.++%@+%++@%. +0x08,0x55,0xea,0x83,0x5e,0xc0, //.+++@%+.+@%. +0x08,0x53,0xef,0xc0,0x5e,0xc0, //.++.@@%.+@%. +0x08,0x50,0xcf,0xa0,0x5e,0xc0, //.++.%@%.+@%. +0x0a,0x50,0xae,0x50,0x5e,0xc0, //.%+.%@+.+@%. +0xef,0xe8,0x5a,0x0a,0xff,0xfe, //@@@++%.%@@@@ + + +/* N */ +0xcf,0xfa,0x00,0x03,0xef,0xfe, //%@@%....@@@@ +0x08,0xee,0x30,0x00,0x0a,0xa0, //.+@@.....%%. +0x08,0xaf,0xc0,0x00,0x08,0x80, //.+%@%....++. +0x08,0x8e,0xe5,0x00,0x08,0x80, //.++@@+...++. +0x08,0x88,0xee,0x00,0x08,0x80, //.+++@@...++. +0x08,0x80,0xee,0x80,0x08,0x80, //.++.@@+..++. +0x08,0x80,0x5e,0xe0,0x08,0x80, //.++.+@@..++. +0x08,0x80,0x0c,0xfa,0x08,0x80, //.++..%@%.++. +0x08,0x80,0x05,0xee,0x38,0x80, //.++..+@@.++. +0x08,0x80,0x00,0xaf,0xa8,0x80, //.++...%@%++. +0x08,0x80,0x00,0x3e,0xe8,0x80, //.++....@@++. +0x08,0x80,0x00,0x0a,0xfc,0x80, //.++....%@%+. +0x08,0x80,0x00,0x00,0xee,0x80, //.++.....@@+. +0x08,0xa0,0x00,0x00,0x8c,0x80, //.+%.....+%+. +0xef,0xfe,0x30,0x00,0x0c,0x80, //@@@@.....%+. + + +/* O */ +0x00,0x05,0xcf,0xfe,0x80,0x00, //...+%@@@+... +0x00,0x8e,0xc3,0x08,0xea,0x00, //..+@%..+@%.. +0x05,0xee,0x00,0x00,0xae,0x80, //.+@@....%@+. +0x0c,0xe8,0x00,0x00,0x3e,0xe0, //.%@+.....@@. +0x3e,0xe3,0x00,0x00,0x0e,0xe5, //.@@......@@+ +0x5e,0xe0,0x00,0x00,0x0c,0xe8, //+@@......%@+ +0x5e,0xe0,0x00,0x00,0x0a,0xfa, //+@@......%@% +0x8e,0xc0,0x00,0x00,0x0a,0xfa, //+@%......%@% +0x5e,0xe0,0x00,0x00,0x0a,0xfa, //+@@......%@% +0x5e,0xe0,0x00,0x00,0x0c,0xe8, //+@@......%@+ +0x0e,0xe3,0x00,0x00,0x0e,0xe5, //.@@......@@+ +0x0a,0xe8,0x00,0x00,0x3e,0xe0, //.%@+.....@@. +0x03,0xee,0x00,0x00,0xae,0x80, //..@@....%@+. +0x00,0x8e,0xc3,0x08,0xea,0x00, //..+@%..+@%.. +0x00,0x05,0xcf,0xfe,0x80,0x00, //...+%@@@+... + + +/* P */ +0x8e,0xff,0xff,0xfe,0xc5,0x00, //+@@@@@@@%+.. +0x03,0xee,0x00,0x03,0xce,0x80, //..@@....%@+. +0x03,0xee,0x00,0x00,0x0e,0xe3, //..@@.....@@. +0x03,0xee,0x00,0x00,0x0c,0xe5, //..@@.....%@+ +0x03,0xee,0x00,0x00,0x0c,0xe5, //..@@.....%@+ +0x03,0xee,0x00,0x00,0x3e,0xe3, //..@@.....@@. +0x03,0xee,0x00,0x05,0xce,0x80, //..@@...+%@+. +0x03,0xef,0xff,0xff,0xc5,0x00, //..@@@@@@%+.. +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0x03,0xee,0x00,0x00,0x00,0x00, //..@@........ +0xaf,0xff,0xe5,0x00,0x00,0x00, //%@@@@+...... + + +/* Q */ +0x00,0x08,0xef,0xfe,0x50,0x00, //...+@@@@+... +0x00,0xaf,0xa0,0x0a,0xea,0x00, //..%@%..%@%.. +0x08,0xec,0x00,0x00,0xae,0x50, //.+@%....%@+. +0x0c,0xe5,0x00,0x00,0x5e,0xc0, //.%@+....+@%. +0x3e,0xe3,0x00,0x00,0x0e,0xe3, //.@@......@@. +0x5e,0xe0,0x00,0x00,0x0e,0xe5, //+@@......@@+ +0x8e,0xc0,0x00,0x00,0x0c,0xe8, //+@%......%@+ +0x8e,0xc0,0x00,0x00,0x0c,0xe8, //+@%......%@+ +0x8e,0xc0,0x00,0x00,0x0c,0xe8, //+@%......%@+ +0x5e,0xc0,0x00,0x00,0x0c,0xe5, //+@%......%@+ +0x3e,0xe8,0xef,0xc0,0x0e,0xe5, //.@@+@@%..@@+ +0x0e,0xec,0x85,0xea,0x3e,0xe0, //.@@%++@%.@@. +0x08,0xee,0x00,0xce,0x8c,0x80, //.+@@..%@+%+. +0x00,0xaf,0xa0,0x8e,0xfc,0x00, //..%@%.+@@%.. +0x00,0x05,0xef,0xff,0xe0,0x30, //...+@@@@@... +0x00,0x00,0x00,0x0e,0xea,0xa0, //.......@@%%. +0x00,0x00,0x00,0x05,0xee,0x80, //.......+@@+. + + +/* R */ +0x8e,0xff,0xff,0xfe,0xc3,0x00, //+@@@@@@@%... +0x03,0xee,0x00,0x08,0xee,0x50, //..@@...+@@+. +0x03,0xee,0x00,0x00,0x8e,0xc0, //..@@....+@%. +0x03,0xee,0x00,0x00,0x5e,0xe0, //..@@....+@@. +0x03,0xee,0x00,0x00,0x5e,0xc0, //..@@....+@%. +0x03,0xee,0x00,0x00,0x8e,0xa0, //..@@....+@%. +0x03,0xee,0x00,0x08,0xee,0x00, //..@@...+@@.. +0x03,0xef,0xff,0xfe,0xa0,0x00, //..@@@@@@%... +0x03,0xee,0x05,0xec,0x00,0x00, //..@@.+@%.... +0x03,0xee,0x00,0xce,0x80,0x00, //..@@..%@+... +0x03,0xee,0x00,0x5e,0xe0,0x00, //..@@..+@@... +0x03,0xee,0x00,0x0c,0xe8,0x00, //..@@...%@+.. +0x03,0xee,0x00,0x08,0xee,0x00, //..@@...+@@.. +0x03,0xee,0x00,0x00,0xee,0x80, //..@@....@@+. +0x8e,0xff,0xe5,0x00,0x8e,0xfc, //+@@@@+..+@@% + + +/* S */ +0x00,0x3c,0xef,0xfc,0x8a,0x00, //...%@@@%+%.. +0x03,0xca,0x30,0x3c,0xfe,0x00, //..%%...%@@.. +0x0c,0xe0,0x00,0x00,0xae,0x30, //.%@.....%@.. +0x0e,0xc0,0x00,0x00,0x3a,0x50, //.@%......%+. +0x0e,0xe0,0x00,0x00,0x00,0x00, //.@@......... +0x0a,0xfe,0x50,0x00,0x00,0x00, //.%@@+....... +0x00,0x8e,0xfe,0xa3,0x00,0x00, //..+@@@%..... +0x00,0x00,0x8e,0xfe,0xa0,0x00, //....+@@@%... +0x00,0x00,0x00,0x5c,0xfc,0x00, //......+%@%.. +0x00,0x00,0x00,0x00,0xce,0x80, //........%@+. +0x5a,0x00,0x00,0x00,0x3e,0xc0, //+%.......@%. +0x3c,0x80,0x00,0x00,0x0e,0xc0, //.%+......@%. +0x0e,0xe3,0x00,0x00,0x5c,0x80, //.@@.....+%+. +0x0c,0xfe,0x50,0x05,0xcc,0x00, //.%@@+..+%%.. +0x08,0xa8,0xef,0xfe,0xa0,0x00, //.+%+@@@@%... + + +/* T */ +0x0c,0xff,0xff,0xff,0xff,0xa0, //.%@@@@@@@@%. +0x0e,0xc3,0x3e,0xe0,0x3c,0xc0, //.@%..@@..%%. +0x3a,0x50,0x3e,0xe0,0x05,0xa3, //.%+..@@..+%. +0x58,0x00,0x3e,0xe0,0x00,0x83, //++...@@...+. +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x0c,0xff,0xff,0xa0,0x00, //...%@@@@%... + + +/* U */ +0xcf,0xff,0xc0,0x03,0xef,0xfa, //%@@@%...@@@% +0x0a,0xe8,0x00,0x00,0x0a,0x50, //.%@+.....%+. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x0a,0xe8,0x00,0x00,0x08,0x50, //.%@+.....++. +0x08,0xea,0x00,0x00,0x38,0x30, //.+@%.....+.. +0x00,0xee,0x80,0x05,0xca,0x00, //..@@+..+%%.. +0x00,0x3a,0xef,0xfc,0x50,0x00, //...%@@@%+... + + +/* V */ +0xef,0xff,0xa0,0x05,0xef,0xfa, //@@@@%..+@@@% +0x0a,0xfa,0x00,0x00,0x3a,0x50, //.%@%.....%+. +0x05,0xec,0x00,0x00,0x5a,0x00, //.+@%....+%.. +0x03,0xee,0x00,0x00,0xaa,0x00, //..@@....%%.. +0x00,0xce,0x50,0x00,0xa5,0x00, //..%@+...%+.. +0x00,0x8e,0xa0,0x05,0xa3,0x00, //..+@%..+%... +0x00,0x5e,0xc0,0x08,0xa0,0x00, //..+@%..+%... +0x00,0x0e,0xe3,0x0a,0x80,0x00, //...@@..%+... +0x00,0x0a,0xe8,0x38,0x30,0x00, //...%@+.+.... +0x00,0x08,0xea,0x8a,0x00,0x00, //...+@%+%.... +0x00,0x03,0xee,0xaa,0x00,0x00, //....@@%%.... +0x00,0x00,0xee,0xa5,0x00,0x00, //....@@%+.... +0x00,0x00,0xaf,0xe0,0x00,0x00, //....%@@..... +0x00,0x00,0x5e,0xa0,0x00,0x00, //....+@%..... +0x00,0x00,0x3a,0x50,0x00,0x00, //.....%+..... + + +/* W */ +0xef,0xfc,0xcf,0xfe,0x5e,0xfe, //@@@%%@@@+@@@ +0x3e,0xc0,0x0c,0xe3,0x05,0xa3, //.@%..%@..+%. +0x3e,0xc0,0x0c,0xe3,0x08,0xa0, //.@%..%@..+%. +0x0c,0xe0,0x0a,0xe5,0x0a,0xa0, //.%@..%@+.%%. +0x0a,0xe3,0x0c,0xe8,0x0a,0x80, //.%@..%@+.%+. +0x08,0xc5,0x0e,0xfa,0x0a,0x50, //.+%+.@@%.%+. +0x05,0xc8,0x3a,0xec,0x38,0x30, //.+%+.%@%.+.. +0x03,0xea,0x8a,0xee,0x58,0x00, //..@%+%@@++.. +0x00,0xec,0xaa,0xce,0x8a,0x00, //..@%%%%@+%.. +0x00,0xce,0xa8,0xae,0xa8,0x00, //..%@%+%@%+.. +0x00,0xae,0xa5,0x8c,0xc5,0x00, //..%@%++%%+.. +0x00,0x8e,0xe0,0x5e,0xe3,0x00, //..+@@.+@@... +0x00,0x5e,0xc0,0x3e,0xe0,0x00, //..+@%..@@... +0x00,0x3e,0xa0,0x0e,0xc0,0x00, //...@%..@%... +0x00,0x0a,0x50,0x0a,0x80,0x00, //...%+..%+... + + +/* X */ +0x8e,0xff,0xe0,0x0c,0xff,0xe5, //+@@@@..%@@@+ +0x03,0xee,0x00,0x00,0xae,0x30, //..@@....%@.. +0x00,0xae,0x80,0x00,0xa5,0x00, //..%@+...%+.. +0x00,0x3e,0xe0,0x0a,0xa0,0x00, //...@@..%%... +0x00,0x0a,0xe8,0x38,0x30,0x00, //...%@+.+.... +0x00,0x03,0xee,0xaa,0x00,0x00, //....@@%%.... +0x00,0x00,0x8e,0xe3,0x00,0x00, //....+@@..... +0x00,0x00,0x3e,0xe5,0x00,0x00, //.....@@+.... +0x00,0x00,0x8c,0xec,0x00,0x00, //....+%@%.... +0x00,0x00,0xc8,0xee,0x50,0x00, //....%+@@+... +0x00,0x08,0xc0,0x8e,0xc0,0x00, //...+%.+@%... +0x00,0x0a,0x50,0x0e,0xe5,0x00, //...%+..@@+.. +0x00,0x8c,0x00,0x05,0xec,0x00, //..+%...+@%.. +0x03,0xc8,0x00,0x00,0xce,0x80, //..%+....%@+. +0xaf,0xfe,0x80,0x0c,0xff,0xfc, //%@@@+..%@@@% + + +/* Y */ +0xaf,0xff,0xe0,0x0a,0xff,0xe8, //%@@@@..%@@@+ +0x08,0xec,0x00,0x00,0x8c,0x50, //.+@%....+%+. +0x00,0xee,0x30,0x00,0xaa,0x00, //..@@....%%.. +0x00,0x8e,0xa0,0x05,0xa3,0x00, //..+@%..+%... +0x00,0x3e,0xe0,0x0c,0xc0,0x00, //...@@..%%... +0x00,0x0a,0xe8,0x5a,0x50,0x00, //...%@++%+... +0x00,0x05,0xee,0xce,0x00,0x00, //...+@@%@.... +0x00,0x00,0xcf,0xe8,0x00,0x00, //....%@@+.... +0x00,0x00,0x8e,0xe3,0x00,0x00, //....+@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x3e,0xe0,0x00,0x00, //.....@@..... +0x00,0x0c,0xff,0xff,0xa0,0x00, //...%@@@@%... + + +/* Z */ +0x03,0xef,0xff,0xff,0xff,0xe0, //..@@@@@@@@@. +0x08,0xee,0x50,0x00,0x8c,0x80, //.+@@+...+%+. +0x0c,0xe0,0x00,0x00,0xec,0x00, //.%@.....@%.. +0x05,0x30,0x00,0x0a,0xe3,0x00, //.+.....%@... +0x00,0x00,0x00,0x3e,0xa0,0x00, //.......@%... +0x00,0x00,0x00,0xce,0x00,0x00, //......%@.... +0x00,0x00,0x08,0xc8,0x00,0x00, //.....+%+.... +0x00,0x00,0x0e,0xc0,0x00,0x00, //.....@%..... +0x00,0x00,0xae,0x30,0x00,0x00, //....%@...... +0x00,0x03,0xea,0x00,0x00,0x00, //....@%...... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x8c,0x80,0x00,0x03,0x83, //..+%+.....+. +0x00,0xec,0x00,0x00,0x0c,0xc0, //..@%.....%%. +0x0a,0xe3,0x00,0x03,0xcf,0xa0, //.%@.....%@%. +0x3e,0xff,0xff,0xff,0xfe,0x50, //.@@@@@@@@@+. + + +/* [ */ +0x00,0x00,0xcf,0xff,0xfe,0x30, //....%@@@@@.. +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xca,0x00,0x00,0x00, //....%%...... +0x00,0x00,0xcf,0xff,0xfe,0x30, //....%@@@@@.. + + +/* \ */ +0x08,0xc5,0x00,0x00,0x00,0x00, //.+%+........ +0x00,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x00,0x8c,0x30,0x00,0x00,0x00, //..+%........ +0x00,0x3e,0xa0,0x00,0x00,0x00, //...@%....... +0x00,0x0a,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x05,0xc8,0x00,0x00,0x00, //...+%+...... +0x00,0x00,0xcc,0x00,0x00,0x00, //....%%...... +0x00,0x00,0x8c,0x50,0x00,0x00, //....+%+..... +0x00,0x00,0x0e,0xa0,0x00,0x00, //.....@%..... +0x00,0x00,0x0a,0xe3,0x00,0x00, //.....%@..... +0x00,0x00,0x03,0xc8,0x00,0x00, //......%+.... +0x00,0x00,0x00,0xae,0x00,0x00, //......%@.... +0x00,0x00,0x00,0x5c,0x80,0x00, //......+%+... +0x00,0x00,0x00,0x0c,0xc0,0x00, //.......%%... +0x00,0x00,0x00,0x08,0xc5,0x00, //.......+%+.. +0x00,0x00,0x00,0x00,0xea,0x00, //........@%.. +0x00,0x00,0x00,0x00,0xae,0x30, //........%@.. +0x00,0x00,0x00,0x00,0x3c,0x80, //.........%+. +0x00,0x00,0x00,0x00,0x0a,0xe0, //.........%@. + + +/* ] */ +0x0c,0xff,0xff,0xe5,0x00,0x00, //.%@@@@@+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x00,0x00,0x05,0xa5,0x00,0x00, //.....+%+.... +0x0c,0xff,0xff,0xe5,0x00,0x00, //.%@@@@@+.... + + +/* ^ */ +0x00,0x00,0xef,0xe8,0x00,0x00, //....@@@+.... +0x00,0x0a,0xea,0xce,0x30,0x00, //...%@%%@.... +0x00,0x5a,0x30,0x08,0xa0,0x00, //..+%...+%... + + +/* _ */ +0xef,0xff,0xff,0xff,0xff,0xfc, //@@@@@@@@@@@% + + +/* ` */ +0x03,0xae,0xe5,0x00,0x00,0x00, //..%@@+...... +0x00,0x00,0x5a,0x80,0x00,0x00, //....+%+..... + + +/* a */ +0x00,0x5c,0xef,0xfe,0xa0,0x00, //..+%@@@@%... +0x08,0xec,0x30,0x08,0xea,0x00, //.+@%...+@%.. +0x0a,0xfa,0x00,0x00,0xec,0x00, //.%@%....@%.. +0x00,0x00,0x00,0x35,0xec,0x00, //.......+@%.. +0x00,0x3a,0xef,0xca,0xec,0x00, //...%@@%%@%.. +0x05,0xee,0x50,0x00,0xec,0x00, //.+@@+...@%.. +0x0e,0xe3,0x00,0x00,0xec,0x00, //.@@.....@%.. +0x5e,0xe0,0x00,0x00,0xec,0x00, //+@@.....@%.. +0x0e,0xe8,0x00,0x5a,0xec,0x88, //.@@+..+%@%++ +0x03,0xce,0xff,0xc5,0xae,0xe5, //..%@@@%+%@@+ + + +/* b */ +0x03,0x85,0x00,0x00,0x00,0x00, //..++........ +0xae,0xe8,0x00,0x00,0x00,0x00, //%@@+........ +0x05,0xc8,0x00,0x00,0x00,0x00, //.+%+........ +0x05,0xc8,0x00,0x00,0x00,0x00, //.+%+........ +0x05,0xc8,0x00,0x00,0x00,0x00, //.+%+........ +0x05,0xc8,0x00,0x00,0x00,0x00, //.+%+........ +0x05,0xc8,0x5e,0xff,0xc3,0x00, //.+%++@@@%... +0x05,0xca,0xc3,0x05,0xee,0x30, //.+%%%..+@@.. +0x05,0xee,0x30,0x00,0x8e,0xa0, //.+@@....+@%. +0x05,0xea,0x00,0x00,0x5e,0xc0, //.+@%....+@%. +0x05,0xc8,0x00,0x00,0x3e,0xe0, //.+%+.....@@. +0x05,0xc8,0x00,0x00,0x3e,0xe0, //.+%+.....@@. +0x05,0xc8,0x00,0x00,0x5e,0xc0, //.+%+....+@%. +0x05,0xea,0x00,0x00,0xae,0x80, //.+@%....%@+. +0x05,0xcc,0x80,0x05,0xec,0x00, //.+%%+..+@%.. +0x05,0xa3,0xcf,0xfe,0xa0,0x00, //.+%.%@@@%... + + +/* c */ +0x00,0x05,0xcf,0xfe,0xa3,0x00, //...+%@@@%... +0x00,0x8e,0xc3,0x05,0xec,0x00, //..+@%..+@%.. +0x05,0xee,0x00,0x03,0xee,0x30, //.+@@....@@.. +0x0a,0xe8,0x00,0x00,0x33,0x00, //.%@+........ +0x0c,0xe5,0x00,0x00,0x00,0x00, //.%@+........ +0x0c,0xe5,0x00,0x00,0x00,0x00, //.%@+........ +0x0a,0xe8,0x00,0x00,0x00,0x30, //.%@+........ +0x05,0xec,0x00,0x00,0x0a,0x80, //.+@%.....%+. +0x00,0xaf,0xc3,0x03,0xcc,0x00, //..%@%...%%.. +0x00,0x08,0xcf,0xfe,0xa3,0x00, //...+%@@@%... + + +/* d */ +0x00,0x00,0x00,0x03,0x58,0x30, //........++.. +0x00,0x00,0x00,0x3c,0xfe,0x30, //.......%@@.. +0x00,0x00,0x00,0x00,0xae,0x30, //........%@.. +0x00,0x00,0x00,0x00,0xae,0x30, //........%@.. +0x00,0x00,0x00,0x00,0xae,0x30, //........%@.. +0x00,0x00,0x00,0x00,0xae,0x30, //........%@.. +0x00,0x08,0xef,0xfc,0xae,0x30, //...+@@@%%@.. +0x00,0xaf,0xa0,0x0a,0xee,0x30, //..%@%..%@@.. +0x05,0xec,0x00,0x00,0xae,0x30, //.+@%....%@.. +0x0a,0xe8,0x00,0x00,0xae,0x30, //.%@+....%@.. +0x0c,0xe5,0x00,0x00,0xae,0x30, //.%@+....%@.. +0x0c,0xe5,0x00,0x00,0xae,0x30, //.%@+....%@.. +0x0a,0xe5,0x00,0x00,0xae,0x30, //.%@+....%@.. +0x08,0xea,0x00,0x00,0xee,0x30, //.+@%....@@.. +0x00,0xce,0x80,0x3a,0xaf,0xc5, //..%@+..%%@%+ +0x00,0x0a,0xef,0xea,0xac,0x83, //...%@@@%%%+. + + +/* e */ +0x00,0x05,0xcf,0xfe,0xa0,0x00, //...+%@@@%... +0x00,0x8c,0xa0,0x05,0xec,0x00, //..+%%..+@%.. +0x03,0xea,0x00,0x00,0x8c,0x80, //..@%....+%+. +0x0a,0xe5,0x00,0x00,0x5e,0xc0, //.%@+....+@%. +0x0c,0xff,0xff,0xff,0xff,0xc0, //.%@@@@@@@@%. +0x0c,0xe5,0x00,0x00,0x00,0x00, //.%@+........ +0x0a,0xe8,0x00,0x00,0x00,0x00, //.%@+........ +0x05,0xec,0x00,0x00,0x0a,0x80, //.+@%.....%+. +0x00,0xae,0xc3,0x03,0xcc,0x00, //..%@%...%%.. +0x00,0x05,0xcf,0xfe,0xa0,0x00, //...+%@@@%... + + +/* f */ +0x00,0x00,0x05,0xcf,0xfe,0xa0, //.....+%@@@%. +0x00,0x00,0x8c,0xa0,0x0a,0xfa, //....+%%..%@% +0x00,0x00,0xee,0x00,0x05,0x85, //....@@...+++ +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x0c,0xff,0xff,0xff,0xfc,0x00, //.%@@@@@@@%.. +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x05,0xef,0xff,0xff,0xc0,0x00, //.+@@@@@@%... + + +/* g */ +0x00,0x0a,0xef,0xfc,0x8e,0xe8, //...%@@@%+@@+ +0x00,0xce,0x50,0x3c,0xe8,0x85, //..%@+..%@+++ +0x05,0xea,0x00,0x03,0xec,0x00, //.+@%....@%.. +0x05,0xea,0x00,0x03,0xec,0x00, //.+@%....@%.. +0x00,0xce,0x50,0x0a,0xe5,0x00, //..%@+..%@+.. +0x00,0x5c,0xef,0xfc,0x50,0x00, //..+%@@@%+... +0x03,0xc8,0x00,0x00,0x00,0x00, //..%+........ +0x03,0xee,0xa6,0x33,0x00,0x00, //..@@%+...... +0x00,0x8c,0xcc,0xef,0xfc,0x30, //..+%%%@@@%.. +0x0a,0xc0,0x00,0x00,0x3e,0xc0, //.%%......@%. +0x0e,0xc0,0x00,0x00,0x0e,0xc0, //.@%......@%. +0x0a,0xea,0x30,0x03,0xac,0x80, //.%@%....%%+. +0x00,0x5c,0xff,0xfe,0xc5,0x00, //..+%@@@@%+.. + + +/* h */ +0x03,0xaa,0x00,0x00,0x00,0x00, //..%%........ +0xae,0xfa,0x00,0x00,0x00,0x00, //%@@%........ +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xea,0x5e,0xff,0xc3,0x00, //..@%+@@@%... +0x03,0xea,0xc5,0x03,0xee,0x00, //..@%%+..@@.. +0x03,0xee,0x00,0x00,0xae,0x30, //..@@....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x8e,0xff,0xe0,0x0e,0xff,0xe8, //+@@@@..@@@@+ + + +/* i */ +0x00,0x00,0x3e,0xe5,0x00,0x00, //.....@@+.... +0x00,0x00,0x3e,0xe5,0x00,0x00, //.....@@+.... +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x03,0x50,0x00,0x00, //......+..... +0x00,0xaf,0xef,0xe0,0x00,0x00, //..%@@@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0xaf,0xff,0xff,0xfa,0x00, //..%@@@@@@%.. + + +/* j */ +0x00,0x00,0x00,0x0c,0xfc,0x00, //.......%@%.. +0x00,0x00,0x00,0x0c,0xfc,0x00, //.......%@%.. +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x00,0x00,0x00, //............ +0x00,0x00,0x00,0x03,0x55,0x00, //........++.. +0x00,0x00,0x0e,0xee,0xe8,0x00, //.....@@@@+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x00,0x00,0x05,0xc8,0x00, //.......+%+.. +0x00,0x30,0x00,0x08,0xc5,0x00, //.......+%+.. +0x05,0xee,0x30,0x5c,0xa0,0x00, //.+@@..+%%... +0x00,0xae,0xff,0xc5,0x00,0x00, //..%@@@%+.... + + +/* k */ +0x03,0xaa,0x00,0x00,0x00,0x00, //..%%........ +0x8e,0xfc,0x00,0x00,0x00,0x00, //+@@%........ +0x03,0xec,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xec,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xec,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xec,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xec,0x00,0xcf,0xff,0xc0, //..@%..%@@@%. +0x03,0xec,0x00,0x0c,0xc3,0x00, //..@%...%%... +0x03,0xec,0x00,0xcc,0x00,0x00, //..@%..%%.... +0x03,0xec,0x0c,0xc0,0x00,0x00, //..@%.%%..... +0x03,0xec,0xcf,0xe3,0x00,0x00, //..@%%@@..... +0x03,0xee,0x88,0xee,0x00,0x00, //..@@++@@.... +0x03,0xec,0x00,0xaf,0xa0,0x00, //..@%..%@%... +0x03,0xec,0x00,0x0c,0xe8,0x00, //..@%...%@+.. +0x03,0xec,0x00,0x03,0xee,0x30, //..@%....@@.. +0x5e,0xff,0xe0,0x0e,0xff,0xfa, //+@@@@..@@@@% + + +/* l */ +0x00,0x03,0x5c,0xc0,0x00,0x00, //....+%%..... +0x00,0xac,0xcf,0xe0,0x00,0x00, //..%%%@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0x00,0x0e,0xe0,0x00,0x00, //.....@@..... +0x00,0xcf,0xff,0xff,0xfc,0x00, //..%@@@@@@%.. + + +/* m */ +0x03,0x30,0x00,0x00,0x00,0x00, //............ +0xcf,0xcc,0xfe,0x8a,0xef,0xc0, //%@%%@@+%@@%. +0x0e,0xe8,0x0e,0xea,0x0a,0xe5, //.@@+.@@%.%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0x0e,0xc0,0x0c,0xe3,0x0a,0xe5, //.@%..%@..%@+ +0xef,0xfc,0xcf,0xfe,0x8e,0xfe, //@@@%%@@@+@@@ + + +/* n */ +0x3a,0xca,0x5c,0xff,0xc3,0x00, //.%%%+%@@%... +0x38,0xea,0xc5,0x03,0xee,0x00, //.+@%%+..@@.. +0x03,0xee,0x30,0x00,0xae,0x30, //..@@....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x03,0xea,0x00,0x00,0xae,0x30, //..@%....%@.. +0x8e,0xff,0xe0,0x0e,0xff,0xe8, //+@@@@..@@@@+ + + +/* o */ +0x00,0x08,0xef,0xfe,0x80,0x00, //...+@@@@+... +0x00,0xce,0xa0,0x0a,0xec,0x00, //..%@%..%@%.. +0x08,0xea,0x00,0x00,0xae,0x80, //.+@%....%@+. +0x0e,0xe3,0x00,0x00,0x3e,0xe0, //.@@......@@. +0x3e,0xe0,0x00,0x00,0x0e,0xe3, //.@@......@@. +0x3e,0xe0,0x00,0x00,0x0e,0xe3, //.@@......@@. +0x0e,0xe3,0x00,0x00,0x3e,0xe0, //.@@......@@. +0x08,0xc8,0x00,0x00,0x8e,0xa0, //.+%+....+@%. +0x00,0xce,0x80,0x08,0xec,0x00, //..%@+..+@%.. +0x00,0x08,0xef,0xfe,0x80,0x00, //...+@@@@+... + + +/* p */ +0x8a,0xca,0x8e,0xfe,0xc3,0x00, //+%%%+@@@%... +0x3a,0xea,0xc5,0x05,0xee,0x50, //.%@%%+.+@@+. +0x03,0xee,0x00,0x00,0x5e,0xc0, //..@@....+@%. +0x03,0xea,0x00,0x00,0x0e,0xe0, //..@%.....@@. +0x03,0xea,0x00,0x00,0x0e,0xe3, //..@%.....@@. +0x03,0xea,0x00,0x00,0x0e,0xe3, //..@%.....@@. +0x03,0xea,0x00,0x00,0x3e,0xe0, //..@%.....@@. +0x03,0xec,0x00,0x00,0x8e,0xa0, //..@%....+@%. +0x03,0xec,0xa0,0x08,0xee,0x00, //..@%%..+@@.. +0x03,0xea,0xae,0xfe,0xa0,0x00, //..@%%@@@%... +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0x03,0xea,0x00,0x00,0x00,0x00, //..@%........ +0xaf,0xff,0xe3,0x00,0x00,0x00, //%@@@@....... + + +/* q */ +0x00,0x08,0xef,0xea,0x38,0x30, //...+@@@%.+.. +0x00,0xce,0xa0,0x0a,0xce,0x30, //..%@%..%%@.. +0x08,0xea,0x00,0x00,0xce,0x30, //.+@%....%@.. +0x0c,0xe5,0x00,0x00,0xce,0x30, //.%@+....%@.. +0x0e,0xe3,0x00,0x00,0xce,0x30, //.@@.....%@.. +0x0e,0xe3,0x00,0x00,0xce,0x30, //.@@.....%@.. +0x0e,0xe3,0x00,0x00,0xce,0x30, //.@@.....%@.. +0x0a,0xe8,0x00,0x00,0xce,0x30, //.%@+....%@.. +0x00,0xee,0x50,0x3a,0xee,0x30, //..@@+..%@@.. +0x00,0x3a,0xef,0xea,0xce,0x30, //...%@@@%%@.. +0x00,0x00,0x00,0x00,0xce,0x30, //........%@.. +0x00,0x00,0x00,0x00,0xce,0x30, //........%@.. +0x00,0x00,0x00,0x5e,0xff,0xe8, //......+@@@@+ + + +/* r */ +0x3a,0xac,0xe0,0x3c,0xff,0xc0, //.%%%@..%@@%. +0x35,0x6e,0xe5,0xa8,0x3e,0xe3, //.++@@+%+.@@. +0x00,0x0c,0xe8,0x30,0x03,0x30, //...%@+...... +0x00,0x0c,0xe5,0x00,0x00,0x00, //...%@+...... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x8e,0xff,0xff,0xfc,0x00,0x00, //+@@@@@@%.... + + +/* s */ +0x00,0x0a,0xef,0xfe,0xac,0x00, //...%@@@@%%.. +0x00,0xce,0x50,0x08,0xee,0x00, //..%@+..+@@.. +0x00,0xea,0x00,0x00,0x8c,0x30, //..@%....+%.. +0x00,0xce,0x50,0x00,0x05,0x30, //..%@+....+.. +0x00,0x3a,0xee,0xc5,0x00,0x00, //...%@@%+.... +0x00,0x00,0x05,0xce,0xe8,0x00, //.....+%@@+.. +0x08,0xa0,0x00,0x00,0xae,0x50, //.+%.....%@+. +0x05,0xa5,0x00,0x00,0x3c,0x80, //.+%+.....%+. +0x05,0xee,0x50,0x03,0xae,0x30, //.+@@+...%@.. +0x03,0xca,0xef,0xff,0xc5,0x00, //..%%@@@@%+.. + + +/* t */ +0x00,0x00,0x58,0x00,0x00,0x00, //....++...... +0x00,0x00,0x8a,0x00,0x00,0x00, //....+%...... +0x00,0x00,0xcc,0x00,0x00,0x00, //....%%...... +0x00,0x08,0xec,0x00,0x00,0x00, //...+@%...... +0x0a,0xff,0xff,0xff,0xfc,0x00, //.%@@@@@@@%.. +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x00,0xee,0x00,0x08,0x80, //....@@...++. +0x00,0x00,0xae,0x50,0x5a,0x30, //....%@+.+%.. +0x00,0x00,0x0c,0xff,0xe5,0x00, //.....%@@@+.. + + +/* u */ +0x00,0x88,0x00,0x00,0x38,0x30, //..++.....+.. +0xaf,0xe8,0x00,0x3e,0xfe,0x30, //%@@+...@@@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xc8,0x00,0x00,0xce,0x30, //.+%+....%@.. +0x05,0xea,0x00,0x00,0xee,0x30, //.+@%....@@.. +0x00,0xee,0x50,0x3c,0xcf,0xc5, //..@@+..%%@%+ +0x00,0x5e,0xff,0xe8,0xcc,0x83, //..+@@@@+%%+. + + +/* v */ +0x8e,0xff,0xe0,0x08,0xef,0xe5, //+@@@@..+@@@+ +0x03,0xee,0x00,0x00,0x8c,0x30, //..@@....+%.. +0x00,0xce,0x30,0x00,0xa8,0x00, //..%@....%+.. +0x00,0x5e,0xa0,0x05,0xa3,0x00, //..+@%..+%... +0x00,0x0e,0xe3,0x0c,0xa0,0x00, //...@@..%%... +0x00,0x0a,0xfa,0x5a,0x50,0x00, //...%@%+%+... +0x00,0x03,0xee,0xac,0x00,0x00, //....@@%%.... +0x00,0x00,0xcf,0xe8,0x00,0x00, //....%@@+.... +0x00,0x00,0x5e,0xe0,0x00,0x00, //....+@@..... +0x00,0x00,0x0e,0xa0,0x00,0x00, //.....@%..... + + +/* w */ +0xef,0xfa,0xef,0xfa,0x8e,0xfe, //@@@%@@@%+@@@ +0x3e,0xc0,0x0e,0xe0,0x08,0xc3, //.@%..@@..+%. +0x0c,0xe0,0x0c,0xe3,0x0a,0xa0, //.%@..%@..%%. +0x0a,0xe5,0x0e,0xe8,0x0a,0x50, //.%@+.@@+.%+. +0x05,0xc8,0x5a,0xec,0x5a,0x00, //.+%++%@%+%.. +0x00,0xec,0xac,0xee,0xcc,0x00, //..@%%%@@%%.. +0x00,0xce,0xc8,0xae,0xc8,0x00, //..%@%+%@%+.. +0x00,0x8e,0xe3,0x8e,0xe3,0x00, //..+@@.+@@... +0x00,0x3e,0xc0,0x3e,0xc0,0x00, //...@%..@%... +0x00,0x0c,0x80,0x0c,0xa0,0x00, //...%+..%%... + + +/* x */ +0x0e,0xff,0xfc,0x5e,0xff,0xe0, //.@@@@%+@@@@. +0x00,0x5e,0xe0,0x03,0xa5,0x00, //..+@@...%+.. +0x00,0x0a,0xe8,0x0a,0xa0,0x00, //...%@+.%%... +0x00,0x00,0xce,0xaa,0x00,0x00, //....%@%%.... +0x00,0x00,0x3e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0x3c,0xea,0x00,0x00, //.....%@%.... +0x00,0x00,0xa5,0xae,0x80,0x00, //....%+%@+... +0x00,0x0a,0x80,0x0e,0xe3,0x00, //...%+..@@... +0x00,0xac,0x00,0x05,0xec,0x30, //..%%...+@%.. +0x8e,0xff,0xc0,0x8e,0xff,0xe5, //+@@@%.+@@@@+ + + +/* y */ +0x5e,0xff,0xe5,0x3e,0xff,0xe8, //+@@@@+.@@@@+ +0x00,0xce,0x50,0x00,0xcc,0x30, //..%@+...%%.. +0x00,0x5c,0x80,0x03,0xa5,0x00, //..+%+...%+.. +0x00,0x0e,0xe0,0x08,0xc0,0x00, //...@@..+%... +0x00,0x08,0xc5,0x0c,0xa0,0x00, //...+%+.%%... +0x00,0x03,0xec,0x5a,0x50,0x00, //....@%+%+... +0x00,0x00,0xae,0xac,0x00,0x00, //....%@%%.... +0x00,0x00,0x5e,0xe8,0x00,0x00, //....+@@+.... +0x00,0x00,0x0c,0xe3,0x00,0x00, //.....%@..... +0x00,0x00,0x0a,0xa0,0x00,0x00, //.....%%..... +0x00,0x00,0x3a,0x50,0x00,0x00, //.....%+..... +0x03,0x85,0xaa,0x00,0x00,0x00, //..++%%...... +0x08,0xef,0xc0,0x00,0x00,0x00, //.+@@%....... + + +/* z */ +0x05,0xef,0xff,0xff,0xfe,0x30, //.+@@@@@@@@.. +0x08,0xea,0x00,0x08,0xea,0x00, //.+@%...+@%.. +0x08,0xc0,0x00,0x5e,0xc0,0x00, //.+%...+@%... +0x08,0x80,0x03,0xee,0x00,0x00, //.++...@@.... +0x00,0x00,0x0e,0xe3,0x00,0x00, //.....@@..... +0x00,0x00,0xce,0x50,0x00,0x00, //....%@+..... +0x00,0x0a,0xe8,0x00,0x0a,0xa0, //...%@+...%%. +0x00,0x8e,0xa0,0x00,0x0c,0x80, //..+@%....%+. +0x05,0xec,0x00,0x03,0xce,0x50, //.+@%....%@+. +0x0c,0xff,0xff,0xff,0xfe,0x30, //.%@@@@@@@@.. + + +/* { */ +0x00,0x00,0x00,0x03,0xce,0x80, //........%@+. +0x00,0x00,0x00,0x0c,0xc3,0x00, //.......%%... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x5a,0x30,0x00, //......+%.... +0x00,0x00,0x03,0xcc,0x00,0x00, //......%%.... +0x00,0x00,0x3c,0xa0,0x00,0x00, //.....%%..... +0x00,0x00,0x00,0xcc,0x00,0x00, //......%%.... +0x00,0x00,0x00,0x5a,0x30,0x00, //......+%.... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x3a,0x50,0x00, //.......%+... +0x00,0x00,0x00,0x0e,0xc3,0x00, //.......@%... +0x00,0x00,0x00,0x05,0xce,0x80, //.......+%@+. + + +/* | */ +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... +0x00,0x00,0x08,0x80,0x00,0x00, //.....++..... + + +/* } */ +0x08,0xec,0x30,0x00,0x00,0x00, //.+@%........ +0x00,0x0c,0xc0,0x00,0x00,0x00, //...%%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x03,0xa5,0x00,0x00,0x00, //....%+...... +0x00,0x00,0x8a,0x30,0x00,0x00, //....+%...... +0x00,0x00,0x5e,0xe3,0x00,0x00, //....+@@..... +0x00,0x03,0xec,0x00,0x00,0x00, //....@%...... +0x00,0x05,0xa5,0x00,0x00,0x00, //...+%+...... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x05,0xa3,0x00,0x00,0x00, //...+%....... +0x00,0x0c,0xe0,0x00,0x00,0x00, //...%@....... +0x08,0xec,0x50,0x00,0x00,0x00, //.+@%+....... + + +/* ~ */ +0x03,0xcf,0xea,0x00,0x00,0x00, //..%@@%...... +0x0a,0x80,0xcf,0xc0,0x00,0x88, //.%+.%@%...++ +0x58,0x00,0x08,0xec,0x35,0xa0, //++...+@%.+%. +0x00,0x00,0x00,0x5e,0xfe,0x50, //......+@@@+. + + +/*  */ + +}; + + +static const sgl_font_table_t sgl_ascii_song23_tab[] = { + {.bitmap_index = 0, .adv_w = 192, .box_h = 0, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*( )*/ + {.bitmap_index = 0, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(!)*/ + {.bitmap_index = 96, .adv_w = 192, .box_h = 6, .box_w = 12, .ofs_x = 0, .ofs_y = 15 },/*(")*/ + {.bitmap_index = 132, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(#)*/ + {.bitmap_index = 228, .adv_w = 192, .box_h = 21, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*($)*/ + {.bitmap_index = 354, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(%)*/ + {.bitmap_index = 450, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(&)*/ + {.bitmap_index = 546, .adv_w = 192, .box_h = 6, .box_w = 12, .ofs_x = 0, .ofs_y = 15 },/*(')*/ + {.bitmap_index = 582, .adv_w = 192, .box_h = 21, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(()*/ + {.bitmap_index = 708, .adv_w = 192, .box_h = 21, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*())*/ + {.bitmap_index = 834, .adv_w = 192, .box_h = 12, .box_w = 12, .ofs_x = 0, .ofs_y = 5 },/*(*)*/ + {.bitmap_index = 906, .adv_w = 192, .box_h = 11, .box_w = 12, .ofs_x = 0, .ofs_y = 6 },/*(+)*/ + {.bitmap_index = 972, .adv_w = 192, .box_h = 6, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(,)*/ + {.bitmap_index = 1008, .adv_w = 192, .box_h = 1, .box_w = 12, .ofs_x = 0, .ofs_y = 11 },/*(-)*/ + {.bitmap_index = 1014, .adv_w = 192, .box_h = 3, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(.)*/ + {.bitmap_index = 1032, .adv_w = 192, .box_h = 20, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(/)*/ + {.bitmap_index = 1152, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(0)*/ + {.bitmap_index = 1248, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(1)*/ + {.bitmap_index = 1344, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(2)*/ + {.bitmap_index = 1440, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(3)*/ + {.bitmap_index = 1536, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(4)*/ + {.bitmap_index = 1632, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(5)*/ + {.bitmap_index = 1728, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(6)*/ + {.bitmap_index = 1824, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(7)*/ + {.bitmap_index = 1920, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(8)*/ + {.bitmap_index = 2016, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(9)*/ + {.bitmap_index = 2112, .adv_w = 192, .box_h = 11, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(:)*/ + {.bitmap_index = 2178, .adv_w = 192, .box_h = 12, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(;)*/ + {.bitmap_index = 2250, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(<)*/ + {.bitmap_index = 2346, .adv_w = 192, .box_h = 5, .box_w = 12, .ofs_x = 0, .ofs_y = 9 },/*(=)*/ + {.bitmap_index = 2376, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(>)*/ + {.bitmap_index = 2472, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(?)*/ + {.bitmap_index = 2568, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(@)*/ + {.bitmap_index = 2664, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(A)*/ + {.bitmap_index = 2760, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(B)*/ + {.bitmap_index = 2850, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(C)*/ + {.bitmap_index = 2940, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(D)*/ + {.bitmap_index = 3030, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(E)*/ + {.bitmap_index = 3120, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(F)*/ + {.bitmap_index = 3210, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(G)*/ + {.bitmap_index = 3300, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(H)*/ + {.bitmap_index = 3390, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(I)*/ + {.bitmap_index = 3480, .adv_w = 192, .box_h = 18, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(J)*/ + {.bitmap_index = 3588, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(K)*/ + {.bitmap_index = 3678, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(L)*/ + {.bitmap_index = 3768, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(M)*/ + {.bitmap_index = 3858, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(N)*/ + {.bitmap_index = 3948, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(O)*/ + {.bitmap_index = 4038, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(P)*/ + {.bitmap_index = 4128, .adv_w = 192, .box_h = 17, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(Q)*/ + {.bitmap_index = 4230, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(R)*/ + {.bitmap_index = 4320, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(S)*/ + {.bitmap_index = 4410, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(T)*/ + {.bitmap_index = 4500, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(U)*/ + {.bitmap_index = 4590, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(V)*/ + {.bitmap_index = 4680, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(W)*/ + {.bitmap_index = 4770, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(X)*/ + {.bitmap_index = 4860, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(Y)*/ + {.bitmap_index = 4950, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(Z)*/ + {.bitmap_index = 5040, .adv_w = 192, .box_h = 20, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*([)*/ + {.bitmap_index = 5160, .adv_w = 192, .box_h = 19, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(\)*/ + {.bitmap_index = 5274, .adv_w = 192, .box_h = 20, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(])*/ + {.bitmap_index = 5394, .adv_w = 192, .box_h = 3, .box_w = 12, .ofs_x = 0, .ofs_y = 19 },/*(^)*/ + {.bitmap_index = 5412, .adv_w = 192, .box_h = 1, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(_)*/ + {.bitmap_index = 5418, .adv_w = 192, .box_h = 2, .box_w = 12, .ofs_x = 0, .ofs_y = 19 },/*(`)*/ + {.bitmap_index = 5430, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(a)*/ + {.bitmap_index = 5490, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(b)*/ + {.bitmap_index = 5586, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(c)*/ + {.bitmap_index = 5646, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(d)*/ + {.bitmap_index = 5742, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(e)*/ + {.bitmap_index = 5802, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(f)*/ + {.bitmap_index = 5892, .adv_w = 192, .box_h = 13, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(g)*/ + {.bitmap_index = 5970, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(h)*/ + {.bitmap_index = 6066, .adv_w = 192, .box_h = 15, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(i)*/ + {.bitmap_index = 6156, .adv_w = 192, .box_h = 18, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(j)*/ + {.bitmap_index = 6264, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(k)*/ + {.bitmap_index = 6360, .adv_w = 192, .box_h = 16, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(l)*/ + {.bitmap_index = 6456, .adv_w = 192, .box_h = 11, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(m)*/ + {.bitmap_index = 6522, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(n)*/ + {.bitmap_index = 6582, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(o)*/ + {.bitmap_index = 6642, .adv_w = 192, .box_h = 13, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(p)*/ + {.bitmap_index = 6720, .adv_w = 192, .box_h = 13, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(q)*/ + {.bitmap_index = 6798, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(r)*/ + {.bitmap_index = 6858, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(s)*/ + {.bitmap_index = 6918, .adv_w = 192, .box_h = 14, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(t)*/ + {.bitmap_index = 7002, .adv_w = 192, .box_h = 11, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(u)*/ + {.bitmap_index = 7068, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(v)*/ + {.bitmap_index = 7128, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(w)*/ + {.bitmap_index = 7188, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(x)*/ + {.bitmap_index = 7248, .adv_w = 192, .box_h = 13, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(y)*/ + {.bitmap_index = 7326, .adv_w = 192, .box_h = 10, .box_w = 12, .ofs_x = 0, .ofs_y = 3 },/*(z)*/ + {.bitmap_index = 7386, .adv_w = 192, .box_h = 20, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*({)*/ + {.bitmap_index = 7506, .adv_w = 192, .box_h = 23, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*(|)*/ + {.bitmap_index = 7644, .adv_w = 192, .box_h = 20, .box_w = 12, .ofs_x = 0, .ofs_y = 1 },/*(})*/ + {.bitmap_index = 7764, .adv_w = 192, .box_h = 4, .box_w = 12, .ofs_x = 0, .ofs_y = 18 },/*(~)*/ + {.bitmap_index = 7788, .adv_w = 192, .box_h = 0, .box_w = 12, .ofs_x = 0, .ofs_y = 0 },/*()*/ +}; + +static const sgl_font_unicode_t song24_unicode = { + .offset = 32, + .tab_offset = 0, + .list = NULL, + .len = 96, +}; + +const sgl_font_t song23 = { + .bitmap = sgl_ascii_song23_bitmap, + .table = sgl_ascii_song23_tab, + .font_table_size = SGL_ARRAY_SIZE(sgl_ascii_song23_tab), + .font_height = 23, + .bpp = 4, + .unicode = &song24_unicode, + .unicode_num = 1, +}; + +#endif diff --git a/User/system/sgl/include/sgl_anim.h b/User/system/sgl/include/sgl_anim.h new file mode 100644 index 0000000..2981031 --- /dev/null +++ b/User/system/sgl/include/sgl_anim.h @@ -0,0 +1,392 @@ +/* source/include/sgl_anim.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_ANIM_H__ +#define __SGL_ANIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include +#include +#include +#include + +#if (CONFIG_SGL_ANIMATION) + +/* Forward declaration of sgl_pos sgl_anim structures */ +struct sgl_pos; +struct sgl_anim; + + +/* Anim path callback */ +typedef void (*sgl_anim_path_cb_t)(struct sgl_anim *anim, int32_t value); +typedef int32_t (*sgl_anim_path_algo_t)(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); + + +/** + * @brief Animation object structure used to manage a single animation instance. + * + * This structure holds all the necessary state and configuration for an animation, + * including timing parameters, value interpolation, callbacks, and linkage in a list. + * All time values (act_delay, act_duration) are in milliseconds. + * + * @data: Pointer to user-defined private data associated with this animation. + * Not used internally by the animation engine; intended for application use. + * + * @next: Pointer to the next animation in a singly-linked list. + * Used internally by the animation scheduler to chain active animations. + * + * @act_delay: Delay time (in ms) before the animation starts after being added to the system. + * The animation will not progress until this delay has elapsed. + * + * @act_duration: Total duration (in ms) of the animation from start_value to end_value. + * + * @start_value: The initial value at the beginning of the animation (after delay). + * + * @end_value: The target value at the end of the animation. + * + * @path_cb: Optional custom callback function to compute intermediate animation values. + * If set, it overrides the built-in path algorithm (`path_algo`). + * + * @path_algo: Predefined interpolation algorithm (e.g., linear, ease-in, ease-out). + * Used only if `path_cb` is NULL. + * + * @finish_cb: Callback function invoked when the animation completes (including repeats). + * May be NULL if no cleanup or notification is needed. + * + * @repeat_cnt: Number of times the animation should repeat. + * - -1: play indefinitely, you can use SGL_ANIM_REPEAT_LOOP + * - 1: play once (no repeat), you can use SGL_ANIM_REPEAT_ONCE + * - n: repeat n times (total plays = n) + * @note Only 30 bits are allocated; max value is 0x3FFFFFFE. + * + * @finished: Flag indicating whether the animation has completed (including all repeats). + * Set to 1 when the animation ends naturally or is stopped. + * + * @auto_free: If set to 1, the animation object will be automatically freed after completion. + * Useful for fire-and-forget animations; ensure memory was allocated dynamically. + */ +typedef struct sgl_anim { + void *data; + struct sgl_anim *next; + uint32_t act_delay; + uint32_t act_duration; + int32_t start_value; + int32_t end_value; + sgl_anim_path_cb_t path_cb; + sgl_anim_path_algo_t path_algo; + void (*finish_cb)(struct sgl_anim *anim); + uint32_t repeat_cnt : 30; + uint32_t finished : 1; + uint32_t auto_free : 1; +} sgl_anim_t; + + +/** + * @brief animation context, it will be used to store status of animation + * @anim_list_head: animation list head + * @anim_list_tail: animation list tail + */ +typedef struct sgl_anim_ctx { + sgl_anim_t *anim_list_head; + sgl_anim_t *anim_list_tail; +} sgl_anim_ctx_t; + + +#define sgl_anim_for_each(anim, head) for ((anim) = (head)->anim_list_head; (anim) != NULL; (anim) = (anim)->next) +#define sgl_anim_for_each_safe(anim, n, head) for (anim = (head)->anim_list_head, n = (anim) ? (anim)->next : NULL; anim != NULL; anim = n, n = (anim) ? (anim)->next : NULL) + +#define SGL_ANIM_REPEAT_LOOP (0x3FFFFFFF) +#define SGL_ANIM_REPEAT_ONCE (1) + + +/* Animation context it will be used internally */ +extern sgl_anim_ctx_t sgl_anim_ctx; + + +/** + * @brief Animation static initialization + * @param anim - Animation object + * @return none + */ +void sgl_anim_init(sgl_anim_t *anim); + + +/** + * @brief dynamic alloc animation object with initialization + * @param none + * @return animation object +*/ +sgl_anim_t* sgl_anim_create(void); + + +/** + * @brief start animation + * @param anim animation object + * @para repeat_cnt repeat count of animation + * @return none +*/ +void sgl_anim_start(sgl_anim_t *anim, uint32_t repeat_cnt); + + +/** + * @brief stop animation + * @param anim animation object + * @return none +*/ +void sgl_anim_stop(sgl_anim_t *anim); + + +/** + * @brief delete animation object + * @param anim animation object + * @return none +*/ +void sgl_anim_delete(sgl_anim_t *anim); + + +/** + * @brief set animation private data + * @param anim animation object + * @param data pointer to private data + * @return none + */ +static inline void sgl_anim_set_data(sgl_anim_t *anim, void *data) +{ + SGL_ASSERT(anim != NULL); + anim->data = data; +} + + +/** + * @brief set animation path callback function + * @param anim animation object + * @param path_cb path callback function + * @param path_algo path algo callback function + * @return none + */ +static inline void sgl_anim_set_path(sgl_anim_t *anim, sgl_anim_path_cb_t path_cb, sgl_anim_path_algo_t path_algo) +{ + SGL_ASSERT(anim != NULL && path_cb != NULL && path_algo != NULL); + anim->path_cb = path_cb; + anim->path_algo = path_algo; +} + + +/** + * @brief set animation start value + * @param anim animation object + * @param value start value + * @return none + */ +static inline void sgl_anim_set_start_value(sgl_anim_t *anim, int32_t value) +{ + SGL_ASSERT(anim != NULL); + anim->start_value = value; +} + + +/** + * @brief set animation end value + * @param anim animation object + * @param value end value + * @return none + */ +static inline void sgl_anim_set_end_value(sgl_anim_t *anim, int32_t value) +{ + SGL_ASSERT(anim != NULL); + anim->end_value = value; +} + + +/** + * @brief set animation active delay time, ms + * @param anim animation object + * @param delay active delay time, ms + * @return none + */ +static inline void sgl_anim_set_act_delay(sgl_anim_t *anim, uint32_t delay_ms) +{ + SGL_ASSERT(anim != NULL); + anim->act_delay = delay_ms; +} + + +/** + * @brief set animation active duration time, ms + * @param anim animation object + * @param duration active duration time, ms + * @return none + */ +static inline void sgl_anim_set_act_duration(sgl_anim_t *anim, uint32_t duration_ms) +{ + SGL_ASSERT(anim != NULL); + anim->act_duration = duration_ms; +} + + +/** + * @brief set finish callback for animation + * @param anim animation object + * @param finish_cb finish callback + * @return none + */ +static inline void sgl_anim_set_finish_cb(sgl_anim_t *anim, void (*finish_cb)(sgl_anim_t *anim)) +{ + SGL_ASSERT(anim != NULL); + anim->finish_cb = finish_cb; +} + + +/** + * @brief check animation is finished or not + * @param anim animation object + * @return true or false + */ +static inline bool sgl_anim_is_finished(sgl_anim_t *anim) +{ + SGL_ASSERT(anim != NULL); + return (bool)anim->finished; +} + + +/** + * @brief set auto free flag for animation + * @param anim animation + * @return none + */ +static inline void sgl_anim_set_auto_free(sgl_anim_t *anim) +{ + SGL_ASSERT(anim != NULL); + anim->auto_free = 1; +} + + +/** + * @brief animation task, it will foreach all animation + * @param none + * @return none + * @note this function should be called in sgl_task() + */ +void sgl_anim_task(void); + + +/** + * Linear animation path calculation function + * + * Calculates the current interpolated value based on elapsed time and total duration + * using linear interpolation. + * + * @param elaps Elapsed time in milliseconds + * @param duration Total animation duration in milliseconds + * @param start Start value + * @param end End value + * + * @return The interpolated value for the current time + * + * @note Returns 'end' if elaps >= duration (animation finished) + * Returns 'start' if elaps == 0 (animation just started) + * Uses 32-bit integer arithmetic to avoid floating-point operations + * for better performance on embedded systems + */ +int32_t sgl_anim_path_linear(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); +#define SGL_ANIM_PATH_LINEAR sgl_anim_path_linear + + +/** + * sgl_anim_path_ease_in_out - Cubic ease-in-out animation path + * + * This function creates a smooth animation curve that starts slow, + * accelerates in the middle, and decelerates at the end. + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_in_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); +#define SGL_ANIM_PATH_EASE_IN_OUT sgl_anim_path_ease_in_out + + +/** + * sgl_anim_path_ease_in - Cubic ease-in animation path + * + * This function creates a smooth animation curve that starts slow, + * accelerates in the after + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_out(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); +#define SGL_ANIM_PATH_EASE_OUT sgl_anim_path_ease_out + + +/** + * sgl_anim_path_ease_in - Cubic ease-in animation path + * + * This function creates a smooth animation curve that starts accelerates, + * accelerates in the after + * + * @param elaps Elapsed time (ms) + * @param duration Total animation duration (ms) + * @param start Start value + * @param end End value + * @return Interpolated value at current time + */ +int32_t sgl_anim_path_ease_in(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); +#define SGL_ANIM_PATH_EASE_IN sgl_anim_path_ease_in + + +/** + * sgl_anim_path_overshoot - Overshoot animation path + * + * This function creates an animation curve that overshoots the target end value + * slightly before settling back to it, creating a natural "bounce" or "spring-like" + * effect for a more dynamic and realistic animation. + * + * @param elaps Elapsed time (ms) since the animation started + * @param duration Total animation duration (ms) + * @param start Initial value of the animated property at the start of the animation + * @param end Target end value of the animated property + * @return Interpolated value of the animated property at the current elapsed time + */ +int32_t sgl_anim_path_overshoot(uint32_t elaps, uint32_t duration, int32_t start, int32_t end); +#define SGL_ANIM_PATH_OVERSHOOT sgl_anim_path_overshoot + + +#endif // ! CONFIG_SGL_ANIMATION + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif // ! __SGL_ANIM_H__ diff --git a/User/system/sgl/include/sgl_cfgfix.h b/User/system/sgl/include/sgl_cfgfix.h new file mode 100644 index 0000000..d361b7a --- /dev/null +++ b/User/system/sgl/include/sgl_cfgfix.h @@ -0,0 +1,230 @@ +/* source/include/sgl_cfgfix.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_CFGFIX_H__ +#define __SGL_CFGFIX_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief sgl config fix file, it will fix the macro if not defined + * @note please add the macro in this file if you want to add new macro into source code + * + * @description: + * + * CONFIG_SGL_FBDEV_PIXEL_DEPTH: + * The pixel depth of framebuffer device, it will be used to define the color type + * + * CONFIG_SGL_FBDEV_ROTATION: + * The rotation of framebuffer device, default: 0 + * + * CONFIG_SGL_FBDEV_RUNTIME_ROTATION: + * If you want to use runtime rotation, please define this macro to 1 + * + * CONFIG_SGL_USE_FBDEV_VRAM: + * If you want to use full framebuffer, please define this macro to 1 + * + * CONFIG_SGL_SYSTICK_MS: + * The macro should be defined to the system tick ms, default: 10 + * + * CONFIG_SGL_COLOR16_SWAP: + * Its for 16 bit color, the color will be swapped + * + * CONFIG_SGL_EVENT_QUEUE_SIZE: + * the size of event queue, default: 32 + * + * CONFIG_SGL_EVENT_CLICK_INTERVAL: + * The click interval, default: 10 + * + * CONFIG_SGL_OBJ_SLOT_DYNAMIC + * If the object slot is dynamic, the object slot size will be dynamic allocated, otherwise, the object + * slot size will be static allocated that you should define CONFIG_SGL_OBJ_NUM_MAX macro + * + * CONFIG_SGL_OBJ_NUM_MAX: + * If CONFIG_SGL_OBJ_SLOT_DYNAMIC is 0 or not defined, you should define CONFIG_SGL_OBJ_NUM_MAX macro + * + * CONFIG_SGL_PIXMAP_BILINEAR_INTERP: + * If you want to use pixmap bilinear interpolation, please define this macro to 1 + * + * CONFIG_SGL_ANIMATION: + * If you want to use animation, please define this macro to 1 + * + * CONFIG_SGL_DEBUG: + * If you want to use debug, please define this macro to 1 + * + * CONFIG_SGL_USE_OBJ_ID: + * If you want to use obj id, please define this macro to 1, at mostly, the CONFIG_SGL_USE_OBJ_ID should be 0 + * + * CONFIG_SGL_HEAP_ALGO: + * The heap algorithm, default: lwmem + * + * CONFIG_SGL_HEAP_MEMORY_SIZE: + * The heap memory size, default: 10240 + * + * CONFIG_SGL_FONT_COMPRESSED: + * If you want to use font compressed, please define this macro to 1 + * + * CONFIG_SGL_FONT_SMALL_TABLE: + * If you want to use font small table, please define this macro to 1 + * + * CONFIG_SGL_LABEL_ROTATION: + * If you want to use label rotation, please define this macro to 1 + * + * CONFIG_SGL_FONT_SONG23: + * If you want to use font song23, please define this macro to 1 + * + * CONFIG_SGL_FONT_CONSOLAS23: + * If you want to use font consolas23, please define this macro to 1 + * + */ + +#ifndef CONFIG_SGL_FBDEV_PIXEL_DEPTH +#define CONFIG_SGL_FBDEV_PIXEL_DEPTH (16) +#endif + +#ifndef CONFIG_SGL_FBDEV_ROTATION +#define CONFIG_SGL_FBDEV_ROTATION (0) +#endif + +#ifndef CONFIG_SGL_FBDEV_RUNTIME_ROTATION +#define CONFIG_SGL_FBDEV_RUNTIME_ROTATION (0) +#endif + +#ifndef CONFIG_SGL_USE_FBDEV_VRAM +#define CONFIG_SGL_USE_FBDEV_VRAM (0) +#endif + +#ifndef CONFIG_SGL_SYSTICK_MS +#define CONFIG_SGL_SYSTICK_MS (10) +#endif + +#ifndef CONFIG_SGL_COLOR16_SWAP +#define CONFIG_SGL_COLOR16_SWAP (0) +#endif + +#ifndef CONFIG_SGL_EVENT_QUEUE_SIZE +#define CONFIG_SGL_EVENT_QUEUE_SIZE (16) +#endif + +#ifndef CONFIG_SGL_EVENT_CLICK_INTERVAL +#define CONFIG_SGL_EVENT_CLICK_INTERVAL (10) +#endif + +#ifndef CONFIG_SGL_DIRTY_AREA_NUM_MAX +#define CONFIG_SGL_DIRTY_AREA_NUM_MAX (16) +#endif + +#ifndef CONFIG_SGL_PIXMAP_BILINEAR_INTERP +#define CONFIG_SGL_PIXMAP_BILINEAR_INTERP (0) +#endif + +#ifndef CONFIG_SGL_ANIMATION +#define CONFIG_SGL_ANIMATION (0) +#endif + +#ifndef CONFIG_SGL_DEBUG +# define CONFIG_SGL_DEBUG (0) +#elif (CONFIG_SGL_DEBUG == 1) +# ifndef CONFIG_SGL_LOG_COLOR +# define CONFIG_SGL_LOG_COLOR (0) +# endif +# ifndef CONFIG_SGL_LOG_LEVEL +# define CONFIG_SGL_LOG_LEVEL (1) +# endif +#endif + +#ifndef CONFIG_SGL_OBJ_USE_NAME +#define CONFIG_SGL_OBJ_USE_NAME (0) +#endif + +#ifndef CONFIG_SGL_HEAP_ALGO +#define CONFIG_SGL_HEAP_ALGO (lwmem) +#endif + +#ifndef CONFIG_SGL_HEAP_MEMORY_SIZE +# define CONFIG_SGL_HEAP_MEMORY_SIZE (10240) +# ifndef CONFIG_SGL_FL_INDEX_MAX +# define CONFIG_SGL_FL_INDEX_MAX (20) +# endif +#endif + +#ifndef CONFIG_SGL_FONT_COMPRESSED +#define CONFIG_SGL_FONT_COMPRESSED (0) +#endif + +#ifndef CONFIG_SGL_FONT_SMALL_TABLE +#define CONFIG_SGL_FONT_SMALL_TABLE (0) +#endif + +#ifndef CONFIG_SGL_LABEL_ROTATION +#define CONFIG_SGL_LABEL_ROTATION (0) +#endif + +#ifndef CONFIG_SGL_FONT_SONG23 +#define CONFIG_SGL_FONT_SONG23 (0) +#endif + +#ifndef CONFIG_SGL_FONT_CONSOLAS14 +#define CONFIG_SGL_FONT_CONSOLAS14 (0) +#endif + +#ifndef CONFIG_SGL_FONT_CONSOLAS23 +#define CONFIG_SGL_FONT_CONSOLAS23 (0) +#endif + +#ifndef CONFIG_SGL_FONT_CONSOLAS24 +#define CONFIG_SGL_FONT_CONSOLAS24 (0) +#endif + +#ifndef CONFIG_SGL_FONT_CONSOLAS32 +#define CONFIG_SGL_FONT_CONSOLAS32 (0) +#endif + +#if !(CONFIG_SGL_THEME_DARK || CONFIG_SGL_THEME_LIGHT) +# ifndef CONFIG_SGL_THEME_DEFAULT +# define CONFIG_SGL_THEME_DEFAULT (1) +# endif +#endif + +#ifndef CONFIG_SGL_BOOT_LOGO +#define CONFIG_SGL_BOOT_LOGO (1) +#endif + +#ifndef CONFIG_SGL_BOOT_ANIMATION +# define CONFIG_SGL_BOOT_ANIMATION (0) +#elif (CONFIG_SGL_ANIMATION == 0) +# undef CONFIG_SGL_BOOT_ANIMATION +# define CONFIG_SGL_BOOT_ANIMATION (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif // !__SGL_CFGFIX_H__ diff --git a/User/system/sgl/include/sgl_core.h b/User/system/sgl/include/sgl_core.h new file mode 100644 index 0000000..b0a9a42 --- /dev/null +++ b/User/system/sgl/include/sgl_core.h @@ -0,0 +1,2164 @@ +/* source/include/sgl_core.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_CORE_H__ +#define __SGL_CORE_H__ + +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* the maximum depth of object*/ +#define SGL_OBJ_DEPTH_MAX (16) +/* the maximum number of drawing buffers */ +#define SGL_DRAW_BUFFER_MAX (2) +/* define default animation tick ms */ +#define SGL_SYSTEM_TICK_MS CONFIG_SGL_SYSTICK_MS + + +#if (CONFIG_SGL_DIRTY_AREA_NUM_MAX) +#define SGL_DIRTY_AREA_NUM_MAX CONFIG_SGL_DIRTY_AREA_NUM_MAX +#endif + +/* the ASCII offset of fonts */ +#define SGL_TEXT_ASCII_OFFSET (32) + + +/** +* @brief This enumeration type defines the alignment of controls in sgl, +* i.e. coordinate positions +*/ +typedef enum sgl_align_type { + SGL_ALIGN_CENTER = 0, + SGL_ALIGN_TOP_MID, + SGL_ALIGN_TOP_LEFT, + SGL_ALIGN_TOP_RIGHT, + SGL_ALIGN_BOT_MID, + SGL_ALIGN_BOT_LEFT, + SGL_ALIGN_BOT_RIGHT, + SGL_ALIGN_LEFT_MID, + SGL_ALIGN_RIGHT_MID, + SGL_ALIGN_VERT_LEFT, + SGL_ALIGN_VERT_RIGHT, + SGL_ALIGN_VERT_MID, + SGL_ALIGN_HORIZ_TOP, + SGL_ALIGN_HORIZ_BOT, + SGL_ALIGN_HORIZ_MID, + SGL_ALIGN_NUM, + +} sgl_align_type_t; + + +/** +* @brief This enumeration type defines the layout of controls in sgl, +* i.e. coordinate positions +*/ +typedef enum sgl_layout_type { + SGL_LAYOUT_NONE = 0, + SGL_LAYOUT_HORIZONTAL = 1, + SGL_LAYOUT_VERTICAL = 2, + SGL_LAYOUT_GRID = 3, + SGL_LAYOUT_NUM = 4, +} sgl_layout_type_t; + + +/** +* @brief This structure is a structure that describes the position of the control, +* where x represents the position of the x coordinate, which is the row coordinate position, +* and y represents the position of the y coordinate, which is the column coordinate position +* +* @x: x coordinate +* @y: y coordinate +*/ +typedef struct sgl_pos { + int16_t x; + int16_t y; +} sgl_pos_t; + + +/** +* @brief This structure describes the size of the object, including width and height, in pixels +* +* @w: width +* @h: height +*/ +typedef struct sgl_size { + int16_t w; + int16_t h; +} sgl_size_t; + + +/** +* @brief This structure describes a rectangular region, where x1 and y1 represent the coordinates +* of the upper left corner of the rectangle, and x2 and y2 represent the coordinates of the +* lower right corner of the rectangle +* +* @x1: x position left corner of the rectangle +* @y1: y position left corner of the rectangle +* @x2: x position right corner of the rectangle +* @y2: y position right corner of the rectangle +*/ +typedef struct sgl_area { + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; +} sgl_area_t; + +#define sgl_rect_t sgl_area_t + + +/** +* @brief This structure defines a 32 bit color bit field +* +* @blue: Blue color component +* @green: Green color component +* @red: Red color component +* @alpha: Color transparency +*/ +typedef union { + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; + } ch; + uint32_t full; +} sgl_color32_t; + + +/** +* @brief This structure defines a 24 bit color bit field +* +* @blue: Blue color component +* @green: Green color component +* @red: Red color component +*/ +typedef union { + struct { + uint8_t blue; + uint8_t green; + uint8_t red; + } ch; + uint8_t full[3]; +} sgl_color24_t; + + +/** +* @brief This structure defines a 16 bit color bit field +* +* @blue: Blue color component +* @green: Green color component +* @red: Red color component +* @alpha: Color transparency +*/ +typedef union { + struct { + uint16_t blue : 5; + uint16_t green : 6; + uint16_t red : 5; + } ch; + uint16_t full; +} sgl_color16_t; + + +/** +* @brief This structure defines a 8 bit color bit field +* +* @blue: Blue color component +* @green: Green color component +* @red: Red color component +* @alpha: Color transparency +*/ +typedef union { + struct { + uint8_t blue : 2; + uint8_t green : 3; + uint8_t red : 3; + } ch; + uint8_t full; +} sgl_color8_t; + + +#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 32) +#define sgl_color_t sgl_color32_t +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 24) +#define sgl_color_t sgl_color24_t +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 16) +#define sgl_color_t sgl_color16_t +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 8) +#define sgl_color_t sgl_color8_t +#endif + + +/** + * @brief This structure defines a surface, which is a rectangular area of the screen. + * @x1: x1 coordinate + * @y1: y1 coordinate + * @x2: x2 coordinate + * @y2: y2 coordinate + * @buffer: buffer pointer + * @size: bytes of buffer + * @w: surf width + * @h: surf height + * @dirty: pointer to dirty area + */ +typedef struct sgl_surf { + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; + sgl_color_t *buffer; + uint32_t size; + uint16_t w; + uint16_t h; + sgl_area_t *dirty; +} sgl_surf_t; + + +/** +* @brief This structure defines an image, with a bitmap pointing to the +* bitmap of the image, while specifying the width and height of the image +* +* @width: pixmap width +* @height: pixmap height +* @format: bitmap format 0: no compression, 1: +* @bitmap: point to image bitmap +*/ +typedef struct sgl_pixmap { + uint32_t width : 13; + uint32_t height : 13; + uint32_t format : 6; + union { + const uint8_t *array; + const uintptr_t addr; + } bitmap; +} sgl_pixmap_t; + + +/** + * @brief This structure defines an icon, with a bitmap pointing to the + * @width: pixmap width + * @height: pixmap height + * @bitmap: point to icon bitmap + */ +typedef struct sgl_icon_pixmap { + uint16_t width; + uint16_t height; + const uint8_t *bitmap; +} sgl_icon_pixmap_t; + + +/** +* @brief Font index table structure, used to describe the bitmap index positions of +* all characters in a font, accelerating the search process +* +* @bitmap_index: point to bitmap index of font +* @adv_w: advance width of character width +* @box_h: height of font +* @box_w: width of font +* @ofs_x: offset of character x position +* @ofs_y: offset of character y position +*/ +typedef struct sgl_font_table { +#if (CONFIG_SGL_FONT_SMALL_TABLE) + const uint16_t bitmap_index; + const uint16_t adv_w; + const uint8_t box_h; + const uint8_t box_w; + const int8_t ofs_x; + const int8_t ofs_y; +#else + const uint32_t bitmap_index; + const uint16_t adv_w; + const uint16_t box_h; + const uint16_t box_w; + const int8_t ofs_x; + const int8_t ofs_y; +#endif +} sgl_font_table_t; + + +/** + * @brief This structure defines a font unicode information, which is a collection of fonts + * @offset: offset of unicode for unicode list + * @len: length of unicode list + * @list: point to unicode list + * @tab_offset: offset of font table + */ +typedef struct sgl_font_unicode { + const uint32_t offset; + const uint32_t len; + const uint32_t *list; + const uint32_t tab_offset; +} sgl_font_unicode_t; + + +/** +* @brief A structure used to describe information about a font, Defining a font set requires +* the use of this structure to describe relevant information +* +* @bitmap: point to bitmap of font +* @table: point to struct sgl_font_table +* @font_table_size: size of struct sgl_font_table +* @font_height: height of font +* @unicode: point to struct sgl_font_unicode struct +* @unicode_num: number of unicode parts +* @base_line: base line of font +* @bpp: The anti aliasing level of the font, only support 2, 4 +* @compress: compress flag, 0: no compress, 1: compress +*/ +typedef struct sgl_font { + const uint8_t *bitmap; + const sgl_font_table_t *table; + const uint16_t font_table_size; + const uint16_t font_height; + const sgl_font_unicode_t *unicode; + const uint32_t unicode_num; + const int16_t base_line; + const uint8_t bpp; + const uint8_t compress; +} sgl_font_t; + + +/** + * @brief Represents a fundamental UI object in the SGL (Simple Graphics Library) framework. + * + * This structure defines a generic GUI element that can be part of a hierarchical display tree. + * Members: + * @area: The logical size (width, height) of the object, used for layout and measurement. + * @coords: The current screen position (x, y) and dimensions after layout calculation. + * @event_fn: Callback function invoked when an event (e.g., touch, click) targets this object. + * @event_data: User-defined context data passed to the event callback. + * @construct_fn: Initialization hook called during object creation to allocate resources or set defaults. + * @parent: Pointer to the parent object; NULL if this is a root-level object. + * @child: Pointer to the first child in the list of children. + * @sibling: Pointer to the next sibling under the same parent. + * @destroyed: (1 bit) Set to 1 when the object is marked for destruction. + * @dirty: (1 bit) Set to 1 when the object needs to be redrawn. + * @hide: (1 bit) Set to 1 to exclude the object from rendering (hidden). + * @needinit: (1 bit) Set to 1 if the object requires deferred initialization. + * @layout: (2 bits) Layout mode for children: + * - 0: No auto-layout + * - 1: Horizontal layout (left to right) + * - 2: Vertical layout (top to bottom) + * - 3: Reserved + * @clickable: (1 bit) Set to 1 if the object can receive click/touch events. + * @movable: (1 bit) Set to 1 if the object can be dragged by the user. + * @border: border width of object + * @flexible: (1 bit, in uint16_t field) Indicates the object can expand to fill available space. + * @evt_leave: (1 bit) Set to 1 if the object should receive "pointer leave" events. + * @pressed: (1 bit) Tracks whether the object is currently being pressed. + * @page: (1 bit) Reserved for page/view switching logic (e.g., in tabbed interfaces). + * @radius: (12 bits) Corner radius in pixels for rounded rectangle rendering (max 4095). + * @name: [Optional] Null-terminated string identifier for debugging or lookup. + * Only present if CONFIG_SGL_OBJ_USE_NAME is defined. + */ +typedef struct sgl_obj { + sgl_area_t area; + sgl_area_t coords; + void (*event_fn)(sgl_event_t *e); + void *event_data; + void (*construct_fn)(sgl_surf_t *surf, struct sgl_obj *obj, sgl_event_t *event); + struct sgl_obj *parent; + struct sgl_obj *child; + struct sgl_obj *sibling; + uint8_t destroyed : 1; + uint8_t dirty : 1; + uint8_t hide : 1; + uint8_t needinit : 1; + uint8_t layout : 2; + uint8_t clickable : 1; + uint8_t movable : 1; + uint8_t border; + uint16_t flexible : 1; + uint16_t focus : 1; + uint16_t pressed : 1; + uint16_t page : 1; + uint16_t radius : 12; +#if CONFIG_SGL_OBJ_USE_NAME + const char *name; +#endif +} sgl_obj_t; + + +/** + * @brief Represents a page object in the SGL graphics system. + * + * An sgl_page_t encapsulates a complete, renderable UI page or screen. + * It combines a base graphical object, a drawing surface, a background color, + * and an optional background pixmap. Pages serve as top-level containers + * for UI elements and can be managed by a page manager or display stack. + * + * Members: + * - obj : Base object (inherits sgl_obj_t), providing position, size, visibility, etc. + * - color : Default background color used when no pixmap is set. + * - alpha : Alpha value for the background color (0-255). + * - pixmap : Optional pointer to a background pixmap. If non-NULL, it typically overrides 'color' + * as the background content during rendering (behavior depends on flush/render logic). + */ +typedef struct sgl_page { + sgl_obj_t obj; + sgl_color_t color; + uint8_t alpha; + const sgl_pixmap_t *pixmap; +} sgl_page_t; + + +/** + * @brief sgl framebuffer information struct + * @buffer: framebuffer, this specify the memory address of the framebuffer + * @buffer_size: framebuffer size + * @xres: x resolution + * @yres: y resolution + * @flush_area: flush area callback function pointer, return the finished flag + */ +typedef struct sgl_fbinfo { + void *buffer[SGL_DRAW_BUFFER_MAX]; + uint32_t buffer_size; + int16_t xres; + int16_t yres; + void (*flush_area)(sgl_area_t *area, sgl_color_t *src); +} sgl_fbinfo_t; + + +/** + * @brief sgl framebuffer device struct + * @fbinfo: framebuffer information, that specify the memory address of the framebuffer and resolution + * @surf: Drawing surface associated with this page; defines the target buffer or area for rendering. + * @dirty_num: dirty area number + * @fb_swap: framebuffer swap flag + * @fb_status: framebuffer status flag + * @dirty: dirty area pool + * @page: current page + */ +typedef struct sgl_fbdev { + sgl_fbinfo_t fbinfo; + sgl_surf_t surf; + uint16_t dirty_num; + volatile uint8_t fb_swap; + volatile uint8_t fb_status; + sgl_area_t dirty[SGL_DIRTY_AREA_NUM_MAX]; + sgl_obj_t *active; +} sgl_fbdev_t; + + +/** + * @brief sgl log print device struct + * @logdev: log print callback function pointer + * @fbdev: framebuffer device + * @last_tick: last tick time, ms + * @tick_ms: tick milliseconds + * @font: system default font + * @rotation: buffer only for rotation + * @angle: angle value only for rotation + */ +typedef struct sgl_system { + void (*logdev)(const char *str); + sgl_fbdev_t fbdev; + volatile uint32_t last_tick; + volatile uint32_t tick_ms; + const sgl_font_t *font; +#if (CONFIG_SGL_FBDEV_ROTATION != 0) + sgl_color_t *rotation; +#elif (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) + sgl_color_t *rotation; + uint16_t angle; +#endif +} sgl_system_t; + + +/** + * @brief for each child object of parent + * @param _child: pointer of child object + * @param parent: pointer of parent object + */ +#define sgl_obj_for_each_child(_child, parent) for (_child = parent->child; _child != NULL; _child = _child->sibling) + + +/** + * @brief for each child object of parent safely + * @param _child: pointer of child object + * @param parent: pointer of parent object + */ +#define sgl_obj_for_each_child_safe(_child, n, parent) for (_child = parent->child, n = (_child ? _child->sibling : NULL); _child != NULL; \ + _child = n, n = (_child ? _child->sibling : NULL)) + +/** + * @brief The macro define the rotation of the framebuffer device + * @param area_dst: destination area + * @param area_src: source area + * @param dst: destination buffer + * @param src: source buffer + * @note it only support 90/180/270 degree rotation + */ +#define sgl_fbdev_rotate_90(area_dst, area_src, dst, src) do { \ + for (uint16_t y = 0; y < height; y++) { \ + for (uint16_t x = 0; x < width; x++) { \ + size_t src_idx = y * width + x; \ + size_t dst_idx = (width - 1 - x) * height + y; \ + dst[dst_idx] = src[src_idx]; \ + } \ + } \ + area_dst.x1 = area_src->y1; \ + area_dst.y1 = SGL_SCREEN_WIDTH - area_src->x2 - 1; \ + area_dst.x2 = sgl_min(area_src->y2, SGL_SCREEN_HEIGHT - 1); \ + area_dst.y2 = sgl_min(SGL_SCREEN_WIDTH - area_src->x1 - 1, SGL_SCREEN_WIDTH - 1); \ + } while(0); + +#define sgl_fbdev_rotate_180(area_dst, area_src, dst, src) do { \ + size_t total = (size_t)(width * height); \ + for (size_t i = 0; i < total; i++) { \ + dst[i] = src[total - 1 - i]; \ + } \ + area_dst.x1 = SGL_SCREEN_WIDTH - area_src->x2 - 1; \ + area_dst.y1 = SGL_SCREEN_HEIGHT - area_src->y2 - 1; \ + area_dst.x2 = SGL_SCREEN_WIDTH - area_src->x1 - 1; \ + area_dst.y2 = SGL_SCREEN_HEIGHT - area_src->y1 - 1; \ + } while(0); + +#define sgl_fbdev_rotate_270(area_dst, area_src, dst, src) do { \ + for (uint16_t y = 0; y < height; y++) { \ + for (uint16_t x = 0; x < width; x++) { \ + size_t src_idx = y * width + x; \ + size_t dst_idx = x * height + (height - 1 - y); \ + dst[dst_idx] = src[src_idx]; \ + } \ + } \ + area_dst.x1 = SGL_SCREEN_HEIGHT - area_src->y2 - 1; \ + area_dst.y1 = area_src->x1; \ + area_dst.x2 = sgl_min(area_dst.x1 + height - 1, SGL_SCREEN_HEIGHT - 1); \ + area_dst.y2 = sgl_min(area_dst.y1 + width - 1, SGL_SCREEN_WIDTH - 1); \ + } while(0); + + +/* dont to use this variable, it is used internally by sgl library */ +extern sgl_system_t sgl_system; + +/** + * @brief Alpha blending table for 4 bpp and 2 bpp + */ +extern const uint8_t sgl_opa4_table[16]; +extern const uint8_t sgl_opa2_table[4]; + + +/** + * @brief register the frame buffer device + * @param fbinfo the frame buffer device information + * @return int, 0 if success, -1 if failed + * @note you must check the result of this function + */ +int sgl_fbdev_register(sgl_fbinfo_t *fbinfo); + + +/** + * @brief set framebuffer device flush ready + * @param none + * @return none + * @note this function must be called in DMA callback function after framebuffer device flush + */ +static inline void sgl_fbdev_flush_ready(void) +{ + sgl_system.fbdev.fb_status |= (1 << sgl_system.fbdev.fb_swap); + + /* change to next framebuffer */ + if (sgl_system.fbdev.fbinfo.buffer[1] != NULL) { + sgl_system.fbdev.surf.buffer = (sgl_color_t *)sgl_system.fbdev.fbinfo.buffer[sgl_system.fbdev.fb_swap ^= 1]; + } +} + + +/** + * @brief check if framebuffer device buffer need to wait ready + * @param fbdev point to the framebuffer device + * @return bool true if need to wait ready, false if not + */ +static inline bool sgl_fbdev_flush_wait_ready(sgl_fbdev_t *fbdev) +{ + return (fbdev->fb_status & (1 << sgl_system.fbdev.fb_swap)) == 0; +} + + +/** + * @brief get framebuffer device buffer resolution width + * @param none + * @return framebuffer device buffer resolution width + */ +static inline int16_t sgl_fbdev_resolution_width(void) +{ + return sgl_system.fbdev.fbinfo.xres; +} + +/** + * @brief get framebuffer device buffer resolution height + * @param none + * @return framebuffer device buffer resolution height + */ +#define SGL_SCREEN_WIDTH sgl_fbdev_resolution_width() + + +/** + * @brief get framebuffer device buffer resolution height + * @param none + * @return framebuffer device buffer resolution height + */ +static inline int16_t sgl_fbdev_resolution_height(void) +{ + return sgl_system.fbdev.fbinfo.yres; +} + +/** + * @brief get framebuffer device buffer resolution width + * @param none + * @return framebuffer device buffer resolution width + */ +#define SGL_SCREEN_HEIGHT sgl_fbdev_resolution_height() + + +/** + * @brief get framebuffer device buffer address + * @param none + * @return framebuffer device buffer address + */ +static inline void* sgl_fbdev_buffer_address(void) +{ + return sgl_system.fbdev.fbinfo.buffer[0]; +} + + +/** + * @brief framebuffer device flush function + * @param area [in] area of flush, that is x1, y1, x2, y2: area of flush + * area contains the coordinates of the area to be flushed + * - x1: x coordinate of the top left corner of the area + * - y1: y coordinate of the top left corner of the area + * - x2: x coordinate of the bottom right corner of the area + * - y2: y coordinate of the bottom right corner of the area + * @param src [in] source color + */ +static inline void sgl_fbdev_flush_area(sgl_area_t *area, sgl_color_t *src) +{ +#if CONFIG_SGL_COLOR16_SWAP + uint16_t w = area->x2 - area->x1 + 1; + uint16_t h = area->y2 - area->y1 + 1; + uint16_t *dst = (uint16_t *)src; + for (size_t i = 0; i < (size_t)(w * h); i++) { + dst[i] = (dst[i] << 8) | (dst[i] >> 8); + } +#endif + +#if (CONFIG_SGL_FBDEV_ROTATION != 0) + uint16_t width = area->x2 - area->x1 + 1; + uint16_t height = area->y2 - area->y1 + 1; + sgl_area_t area_dst = *area; + +#if (CONFIG_SGL_FBDEV_ROTATION == 90) + sgl_fbdev_rotate_90(area_dst, area, sgl_system.rotation, src); +#elif (CONFIG_SGL_FBDEV_ROTATION == 180) + sgl_fbdev_rotate_180(area_dst, area, sgl_system.rotation, src); +#elif (CONFIG_SGL_FBDEV_ROTATION == 270) + sgl_fbdev_rotate_270(area_dst, area, sgl_system.rotation, src); +#else +#error "CONFIG_SGL_FBDEV_ROTATION is invalid rotation value (only 0/90/180/270 supported)" +#endif + sgl_system.fbdev.fbinfo.flush_area(&area_dst, sgl_system.rotation); +#elif (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) + uint16_t width = area->x2 - area->x1 + 1; + uint16_t height = area->y2 - area->y1 + 1; + sgl_area_t area_dst = *area; + + switch (sgl_system.angle) { + case 0: + sgl_system.fbdev.fbinfo.flush_area(area, src); + return; + case 90: + sgl_fbdev_rotate_90(area_dst, area, sgl_system.rotation, src); + break; + case 180: + sgl_fbdev_rotate_180(area_dst, area, sgl_system.rotation, src); + break; + case 270: + sgl_fbdev_rotate_270(area_dst, area, sgl_system.rotation, src); + break; + default: + SGL_LOG_ERROR("invalid angle: %d", sgl_system.angle); + return; + } + sgl_system.fbdev.fbinfo.flush_area(&area_dst, sgl_system.rotation); +#else + sgl_system.fbdev.fbinfo.flush_area(area, src); +#endif +} + + +#if (CONFIG_SGL_FBDEV_RUNTIME_ROTATION) +/** + * @brief set framebuffer device rotation angle + * @param angle [in] rotation angle, that is 0, 90, 180, 270 + * @return none + * @note Rotation angle must be 0, 90, 180, 270 + */ +void sgl_fbdev_set_angle(uint16_t angle); +#endif //CONFIG_SGL_FBDEV_RUNTIME_ROTATION + + +/** + * @brief register log output device + * @param log_puts log output function + * @return none + * @note if you want to use print log into uart or other devices, you must register log output device first + */ +static inline void sgl_logdev_register(void (*puts)(const char *str)) +{ + sgl_system.logdev = puts; +} + + +/** + * @brief log output function + * @param str log string + * @return none + * @note if you want to use printf function, you must register log output device first + */ +static inline void sgl_log_stdout(const char *str) +{ + if (sgl_system.logdev) { + sgl_system.logdev(str); + } +} + + +/** + * @brief get pixmap bytes of per pixel + * @param pixmap pointer to pixmap + * @return pixmap bytes of per pixel + */ +uint8_t sgl_pixmal_get_bytes_per_pixel(const sgl_pixmap_t *pixmap); + + +/** + * @brief get tick milliseconds + * @param none + * @return tick milliseconds + */ +static inline uint32_t sgl_tick_get(void) +{ + return sgl_system.tick_ms; +} + + +/** + * @brief get last tick milliseconds + * @param none + * @return tick milliseconds + */ +static inline uint32_t sgl_last_tick_get(void) +{ + return sgl_system.last_tick; +} + + +/** + * @brief increase tick milliseconds + * @param ms milliseconds + * @return none + * @note in general, you should call this function in the 1ms tick interrupt handler + * of course, you can use polling function to increase tick milliseconds. + */ +static inline void sgl_tick_inc(uint32_t ms) +{ + sgl_system.tick_ms += ms; +} + + +/** + * @brief sync tick milliseconds + * @param none + * @return none + */ +static inline void sgl_tick_sync(void) +{ + sgl_system.last_tick = sgl_system.tick_ms; +} + + +/** + * @brief reset tick milliseconds + * @param none + * @return none + */ +static inline void sgl_tick_reset(void) +{ + sgl_system.tick_ms = 0; +} + + +/** +* @brief converts the color value of an integer into a color structure +* @param: color value +* @return: sgl_color_t +*/ +static inline sgl_color_t sgl_int2color(uint32_t color) +{ + sgl_color_t c; +#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 32) + c.full = color; +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 24) + c.ch.blue = (uint8_t)color; + c.ch.green = (uint8_t)(color >> 8); + c.ch.red = (uint8_t)(color >> 16); +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 16) + c.ch.blue = (uint8_t)(color & 0x1f); + c.ch.green = (uint8_t)((color >> 5) & 0x3f); + c.ch.red = (uint8_t)((color >> 11) & 0x1f); +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 8) + c.ch.blue = (uint8_t)(color & 0x3); + c.ch.green = (uint8_t)((color >> 2) & 0x7); + c.ch.red = (uint8_t)((color >> 5) & 0x7); +#endif + return c; +} + + +/** + * @brief converts the color structure into an integer + * @param: color structure + * @return: integer + */ +static inline uint32_t sgl_color2int(sgl_color_t color) +{ + uint32_t c; +#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == 24) + c = color.ch.blue | (color.ch.green << 8) | (color.ch.red << 16); +#else + c = color.full; +#endif + return c; +} + + +/** +* @brief Inline function that converts the color value of an (r,g,b) into a color structure +* @param: red Red color component +* @param: green Green color component +* @param: blue Blue color component +* @return: sgl_color_t +*/ +static inline sgl_color_t sgl_rgb2color(uint8_t red, uint8_t green, uint8_t blue) +{ + sgl_color_t color; + color.ch.blue = blue; + color.ch.green = green; + color.ch.red = red; + return color; +} + + +/** + * @brief init object node + * @param obj: pointer of object + * @return none + */ +static inline void sgl_obj_node_init(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + + obj->sibling = NULL; + obj->child = NULL; +} + + +/** + * @brief add object to parent + * @param parent: pointer of parent object + * @param obj: pointer of object + * @return none + */ +void sgl_obj_add_child(sgl_obj_t *parent, sgl_obj_t *obj); + + +/** + * @brief remove an object from its parent + * @param obj object to remove + * @return none + */ +void sgl_obj_remove(sgl_obj_t *obj); + + +/** + * @brief check if object has child + * @param obj object + * @return true or false, true means object has child, false means object has no child + */ +static inline bool sgl_obj_has_child(sgl_obj_t *obj) { + SGL_ASSERT(obj != NULL); + return (bool)obj->child; +} + + +/** + * @brief get child of an object + * @param obj the object + * @return the child of the object + */ +static inline sgl_obj_t* sgl_obj_get_child(sgl_obj_t* obj) +{ + SGL_ASSERT(obj != NULL); + return obj->child; +} + + +/** + * @brief check if object has sibling + * @param obj object + * @return true or false, true means object has sibling, false means object has no sibling + */ +static inline bool sgl_obj_has_sibling(sgl_obj_t *obj) { + SGL_ASSERT(obj != NULL); + return (bool)obj->sibling; +} + + +/** + * @brief get sibling of an object + * @param obj the object + * @return the sibling of the object + */ +static inline sgl_obj_t* sgl_obj_get_sibling(sgl_obj_t* obj) +{ + SGL_ASSERT(obj != NULL); + return obj->sibling; +} + + +/** + * @brief get child count of an object + * @param obj object + * @return child count + */ +static inline size_t sgl_obj_get_child_count(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_obj_t *child = NULL; + size_t count = 0; + + sgl_obj_for_each_child(child, obj) { + count ++; + } + + return count; +} + + +/** + * @brief merge an area into global dirty area + * + * This function calculates how much rectangle 'a' would need to grow in each direction (left, right, top, bottom) + * to fully enclose both 'a' and 'b'. The result is the sum of the expansions along all four sides. + * Note: This is not the increase in area, th is a lightweight heuristic for merge cost in bounding-box algorithms. + * + * @param area [in] Pointer to the area + * @return none + */ +void sgl_dirty_area_push(sgl_area_t *area); + + +/** + * @brief set system font + * @param font pointer to font + * @return none + */ +static inline void sgl_set_system_font(const sgl_font_t *font) +{ + SGL_ASSERT(font != NULL); + sgl_system.font = font; +} + + +/** + * @brief get system font + * @param none + * @return pointer to system font + */ +static inline const sgl_font_t* sgl_get_system_font(void) +{ + return sgl_system.font; +} + + +/** + * @brief Set the object to be destroyed + * @param obj: the object to set + * @retval None + * @note this function is used to set the destroyed flag of the object, then next draw cycle, the object will be removed + * the object should be not NULL. + */ +static inline void sgl_obj_set_destroyed(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->destroyed = 1; +} + + +/** + * @brief check object destroyed flag + * @param obj point to object + * @return flag, false - live, true - destroyed + */ +static inline bool sgl_obj_is_destroyed(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->destroyed; +} + + +/** + * @brief Set object to dirty + * @param obj point to object + * @return none + * @note this function will set object to dirty, include its children + */ +static inline void sgl_obj_set_dirty(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->dirty = 1; +} + + +/** + * @brief Clear object dirty flag + * @param obj point to object + * @return none + */ +static inline void sgl_obj_clear_dirty(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->dirty = 0; +} + + +/** + * @brief Clear all dirty areas of the object and its children. + * @param[in] obj The object to clear. + * @return None + * @note This function is used to clear all dirty areas of the object and its children. + */ +void sgl_obj_clear_all_dirty(sgl_obj_t *obj); + + +/** + * @brief check object dirty flag + * @param obj point to object + * @return flag, false - clear, true - dirty + */ +static inline bool sgl_obj_is_dirty(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->dirty; +} + + +/** + * @brief set object need init coords + * @param obj point to object + * @return none + */ +static inline void sgl_obj_needinit(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->needinit = 1; +} + + +/** + * @brief check object if need init coords + * @param obj point to object + * @return flag, true - need init coords + */ +static inline bool sgl_obj_is_needinit(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->needinit; +} + + +/** + * @brief clear object need init coords flag + * @param obj point to object + * @return none + */ +static inline void sgl_obj_clear_needinit(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->needinit = 0; +} + + +/** + * @brief set object hidden flag + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_hidden(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->hide = 1; + sgl_dirty_area_push(&obj->area); +} + + +/** + * @brief set object visible + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_visible(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->hide = 0; + sgl_dirty_area_push(&obj->area); +} + + +/** + * @brief check object hidden flag + * @param obj point to object + * @return flag, false - show, true - hidden + */ +static inline bool sgl_obj_is_hidden(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->hide; +} + + +/** + * @brief set object to clickable + * @param obj point to object + * @return none + * @note if object is clickable, it can receive click events, otherwise it will not receive + */ +static inline void sgl_obj_set_clickable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->clickable = 1; + obj->flexible = 1; +} + + +/** + * @brief set object to unclickable + * @param obj point to object + * @return none + * @note if object is clickable, it can receive click events, otherwise it will not receive + */ +static inline void sgl_obj_set_unclickable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->clickable = 0; + obj->flexible = 0; +} + + +/** + * @brief check object is clickable + * @param obj point to object + * @return true: clickable, false: unclickable + */ +static inline bool sgl_obj_is_clickable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->clickable; +} + + +/** + * @brief set object flexible + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_flexible(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->flexible = 1; +} + + +/** + * @brief set object unflexible + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_unflexible(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->flexible = 0; +} + + +/** + * @brief check object flexible + * @param obj point to object + * @return true or false + */ +static inline bool sgl_obj_is_flexible(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->flexible; +} + + +/** + * @brief set object clickable + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_movable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->movable = 1; +} + + +/** + * @brief set object unmovable + * @param obj point to object + * @return none + */ +static inline void sgl_obj_set_unmovable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + obj->movable = 0; +} + + +/** + * @brief check object movable + * @param obj point to object + * @return true or false + */ +static inline bool sgl_obj_is_movable(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return (bool)obj->movable; +} + + +/** + * @brief update object area + * @param area point to area that need update + * @return none, this function will force update object area + */ +static inline void sgl_obj_update_area(sgl_area_t *area) +{ + sgl_dirty_area_push(area); +} + + +/** + * @brief move object child position + * @param obj point to object + * @param ofs_x: x offset position + * @param ofs_y: y offset position + * @return none + */ +void sgl_obj_move_child_pos(sgl_obj_t *obj, int16_t ofs_x, int16_t ofs_y); + + +/** + * @brief move object child x position + * @param obj point to object + * @param ofs_x: x offset position + * @return none + */ +static inline void sgl_obj_move_child_pos_x(sgl_obj_t *obj, int16_t ofs_x) +{ + sgl_obj_move_child_pos(obj, ofs_x, 0); +} + + +/** + * @brief move object child y position + * @param obj point to object + * @param ofs_y: y offset position + * @return none + */ +static inline void sgl_obj_move_child_pos_y(sgl_obj_t *obj, int16_t ofs_y) +{ + sgl_obj_move_child_pos(obj, 0, ofs_y); +} + + +/** + * @brief zoom object size + * @param obj point to object + * @param zoom zoom size + * @return none + * @note if you want to zoom out, the zoom should be positive, if you want to zoom in, the zoom should be negative + */ +void sgl_obj_size_zoom(sgl_obj_t *obj, int16_t zoom); + + +/** + * @brief move object up a level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_up(sgl_obj_t *obj); + + +/** + * @brief move object down a level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_down(sgl_obj_t *obj); + + +/** + * @brief move object top level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_top(sgl_obj_t *obj); + + +/** + * @brief move object bottom level layout + * @param obj point to object + * @return none + * @note Only move among sibling objects + */ +void sgl_obj_move_bottom(sgl_obj_t *obj); + + +/** + * @brief Set object absolute position + * @param obj point to object + * @param abs_x: x absolute position + * @param abs_y: y absolute position + * @return none + */ +void sgl_obj_set_abs_pos(sgl_obj_t *obj, int16_t abs_x, int16_t abs_y); + + +/** + * @brief Get object absolute position + * @param obj point to object + * @param abs_x: point to x absolute position + * @param abs_y: point to y absolute position + * @return none + */ +static inline sgl_pos_t sgl_obj_get_abs_pos(sgl_obj_t *obj) +{ + sgl_pos_t pos = { + .x = obj->coords.x1, + .y = obj->coords.y1 + }; + return pos; +} + + +/** + * @brief Set object relative position + * @param obj point to object + * @param x: x relative position + * @param y: y relative position + * @return none + * @note This x and y position is relative to the parent object + */ +static inline void sgl_obj_set_pos(sgl_obj_t *obj, int16_t x, int16_t y) +{ + sgl_obj_set_abs_pos(obj, obj->parent->coords.x1 + x, obj->parent->coords.y1 + y); +} + + +/** + * @brief Get object position + * @param obj point to object + * @return sgl_pos_t: position of object + * @note this function will return the top left corner position of the object relative to its parent + */ +static inline sgl_pos_t sgl_obj_get_pos(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + + sgl_pos_t pos; + pos.x = obj->coords.x1 - obj->parent->coords.x1; + pos.y = obj->coords.y1 - obj->parent->coords.y1; + return pos; +} + + +/** + * @brief Set object x relative position + * @param obj point to object + * @param x x position + * @return none + * @note this function will set the x position of the object, it's relative to the parent object + */ +static inline void sgl_obj_set_pos_x(sgl_obj_t *obj, int16_t x) +{ + sgl_obj_set_abs_pos(obj, obj->parent->coords.x1 + x, obj->coords.y1); +} + + +/** + * @brief Get object x relative position + * @param obj point to object + * @return x position, it's relative to the parent object + */ +static inline size_t sgl_obj_get_pos_x(sgl_obj_t *obj) +{ + return (obj->coords.x1 - obj->parent->coords.x1); +} + + +/** + * @brief Set object y relative position + * @param obj point to object + * @param y y position + * @return none + * @note this function will set the y position of the object, it's relative to the parent object + */ +static inline void sgl_obj_set_pos_y(sgl_obj_t *obj, int16_t y) +{ + sgl_obj_set_abs_pos(obj, obj->coords.x1, obj->parent->coords.y1 + y); +} + + +/** + * @brief Get object y relative position + * @param obj point to object + * @return y position, it's relative to the parent object + */ +static inline int16_t sgl_obj_get_pos_y(sgl_obj_t *obj) +{ + return obj->coords.y1 - obj->parent->coords.y1; +} + + +/** + * @brief Set the alignment position of the object relative to its parent object. + * @param obj The object to set the alignment position. + * @param type The alignment type. + * @return none + * @note type should be one of the sgl_align_type_t values: + * - SGL_ALIGN_CENTER : Center the object in the parent object. + * - SGL_ALIGN_TOP_MID : Align the object at the top middle of the parent object. + * - SGL_ALIGN_TOP_LEFT : Align the object at the top left of the parent object. + * - SGL_ALIGN_TOP_RIGHT : Align the object at the top right of the parent object. + * - SGL_ALIGN_BOT_MID : Align the object at the bottom middle of the parent object. + * - SGL_ALIGN_BOT_LEFT : Align the object at the bottom left of the parent object. + * - SGL_ALIGN_BOT_RIGHT : Align the object at the bottom right of the parent object. + * - SGL_ALIGN_LEFT_MID : Align the object at the left middle of the parent object. + * - SGL_ALIGN_RIGHT_MID : Align the object at the right middle of the parent object. + */ +void sgl_obj_set_pos_align(sgl_obj_t *obj, sgl_align_type_t type); + + +/** + * @brief Set the alignment position of the object relative to its sibling object. + * @param ref The reference object, it should be the sibling object. + * @param obj The object to set the alignment position. + * @param type The alignment type. + * @return none + * @note type should be one of the sgl_align_type_t values: + * - SGL_ALIGN_VERT_LEFT : Align the object at the left side of the reference object. + * - SGL_ALIGN_VERT_RIGHT : Align the object at the right side of the reference object. + * - SGL_ALIGN_VERT_MID : Align the object at the middle of the reference object. + * - SGL_ALIGN_HORIZ_TOP : Align the object at the top side of the reference object. + * - SGL_ALIGN_HORIZ_BOT : Align the object at the bottom side of the reference object. + * - SGL_ALIGN_HORIZ_MID : Align the object at the middle of the reference object. + */ +void sgl_obj_set_pos_align_ref(sgl_obj_t *ref, sgl_obj_t *obj, sgl_align_type_t type); + + +/** + * @brief Set object size + * @param obj point to object + * @param width: width that you want to set + * @param height: height that you want to set + * @return none + */ +static inline void sgl_obj_set_size(sgl_obj_t *obj, int16_t width, int16_t height) +{ + SGL_ASSERT(obj != NULL); + obj->coords.x2 = obj->coords.x1 + width - 1; + obj->coords.y2 = obj->coords.y1 + height - 1; + sgl_obj_set_dirty(obj); +} + + +/** + * @brief Get object size + * @param obj point to object + * @return sgl_size_t: size of object + */ +static inline sgl_size_t sgl_obj_get_size(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_size_t size; + size.w = obj->coords.x2 - obj->coords.x1 + 1; + size.h = obj->coords.y2 - obj->coords.y1 + 1; + return size; +} + + +/** + * @brief Set object width + * @param obj point to object + * @param width: width that you want to set + * @return none + */ +static inline void sgl_obj_set_width(sgl_obj_t *obj, int16_t width) +{ + SGL_ASSERT(obj != NULL); + obj->coords.x2 = obj->coords.x1 + width - 1; +} + + +/** + * @brief Get object width + * @param obj point to object + * @return object width + */ +static inline int16_t sgl_obj_get_width(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return obj->coords.x2 - obj->coords.x1 + 1; +} + + +/** + * @brief Set object height + * @param obj point to object + * @param height: height that you want to set + * @return none + */ +static inline void sgl_obj_set_height(sgl_obj_t *obj, int16_t height) +{ + SGL_ASSERT(obj != NULL); + obj->coords.y2 = obj->coords.y1 + height - 1; +} + + +/** + * @brief Get object height + * @param obj point to object + * @return object height + */ +static inline int16_t sgl_obj_get_height(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return obj->coords.y2 - obj->coords.y1 + 1; +} + + +/** + * @brief Set object border width + * @param obj point to object + * @param border: border width that you want to set + * @return none + */ +static inline void sgl_obj_set_border_width(sgl_obj_t *obj, uint8_t border) +{ + SGL_ASSERT(obj != NULL); + obj->border = sgl_min3(border, sgl_obj_get_width(obj) / 2, sgl_obj_get_height(obj) / 2); +} + + +/** + * @brief Get object border width + * @param obj point to object + * @return object border width + */ +static inline int16_t sgl_obj_get_border_width(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return obj->border; +} + + +/** + * @brief Get object fill rectangle + * @param obj point to object + * @return object fill rectangle + * @note This function is used to obtain the inner area of an object, i.e., the region excluding its borders. + */ +static inline sgl_area_t sgl_obj_get_fill_rect(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_area_t fill = { + .x1 = sgl_max(obj->coords.x1 + obj->border, obj->area.x1), + .y1 = sgl_max(obj->coords.y1 + obj->border, obj->area.y1), + .x2 = sgl_min(obj->coords.x2 - obj->border, obj->area.x2), + .y2 = sgl_min(obj->coords.y2 - obj->border, obj->area.y2), + }; + return fill; +} + + +/** + * @brief Set object event callback function + * @param obj point to object + * @param event_fn: event callback function + * @param data: event callback function data + * @return none + */ +static inline void sgl_obj_set_event_cb(sgl_obj_t *obj, void (*event_fn)(sgl_event_t *e), void *data) +{ + SGL_ASSERT(obj != NULL); + obj->event_fn = event_fn; + obj->event_data = data; + obj->clickable = 1; +} + + +/** + * @brief set the radius of object + * @param obj object + * @param radius: radius that you want to set + * @return none + * @note if radius is larger than object's width or height, fix radius will be returned + */ +void sgl_obj_set_radius(sgl_obj_t *obj, size_t radius); + + +/** + * @brief get the radius of object + * @param obj object + * @return object radius + */ +static inline int16_t sgl_obj_get_radius(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + return obj->radius; +} + + +/** + * @brief set current object as screen object + * @param obj object, that you want to set an object as active page + * @return none + */ +void sgl_screen_load(sgl_obj_t *obj); + + +/** + * @brief get current screen object + * @param none + * @return active current screen object + */ +static inline sgl_obj_t* sgl_screen_act(void) +{ + return sgl_system.fbdev.active; +} + + +/** + * @brief get active page + * @param none + * @return page: active page + */ +static inline sgl_page_t* sgl_page_get_active(void) +{ + return (sgl_page_t*)sgl_system.fbdev.active; +} + + +/** + * @brief sgl task handle function with sync mode + * @param none + * @return none + * @note you can call this function to force update screen + */ +void sgl_task_handle_sync(void); + + +/** + * @brief sgl task handle function + * @param none + * @return none + * @note this function should be called in main loop or timer or thread + */ +static inline void sgl_task_handle(void) +{ + /* If the system tick time has not been reached, skip directly. */ + if ((sgl_tick_get() - sgl_last_tick_get()) < SGL_SYSTEM_TICK_MS) { + return; + } + + sgl_tick_sync(); + /* If the system tick time has been reached, execute the task. */ + sgl_task_handle_sync(); +} + + +/** + * @brief Create an object + * @param parent parent object + * @return sgl_obj_t + * @note if parent is NULL, the object will be as an new page + */ +sgl_obj_t* sgl_obj_create(sgl_obj_t *parent); + + +/** + * @brief free an object + * @param obj: object to free + * @retval none + * @note this function will free all the children of the object + */ +void sgl_obj_free(sgl_obj_t *obj); + + +/** + * @brief delete object + * @param obj point to object + * @return none + * @note this function will set object and his childs to be destroyed, then next draw cycle, the object will be removed. + * if object is NULL, the all objects of active page will be delete, but the page object will not be deleted. + * if object is a page, the page object will be deleted and all its children will be deleted. + */ +void sgl_obj_delete(sgl_obj_t *obj); + + +/** + * @brief delete object + * @param obj point to object + * @return none + * @note this function will take effect immediately + */ +static inline void sgl_obj_delete_sync(sgl_obj_t *obj) +{ + sgl_obj_delete(obj); + sgl_task_handle_sync(); +} + + +/** + * @brief color mixer + * @param fg_color : foreground color + * @param bg_color : background color + * @param factor : color mixer factor + * @return sgl_color_t: mixed color + */ +static inline sgl_color_t sgl_color_mixer(sgl_color_t fg_color, sgl_color_t bg_color, uint8_t factor) +{ + sgl_color_t ret; +#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB332) + + ret.ch.red = bg_color.ch.red + ((fg_color.ch.red - bg_color.ch.red) * (factor >> 5) >> 3); + ret.ch.green = bg_color.ch.green + ((fg_color.ch.green - bg_color.ch.green) * (factor >> 5) >> 3); + ret.ch.blue = bg_color.ch.blue + ((fg_color.ch.blue - bg_color.ch.blue) * (factor >> 6) >> 2); + +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB565) + + factor = (uint32_t)((uint32_t)factor + 4) >> 3; + uint32_t bg = (uint32_t)((uint32_t)bg_color.full | ((uint32_t)bg_color.full << 16)) & 0x07E0F81F; + uint32_t fg = (uint32_t)((uint32_t)fg_color.full | ((uint32_t)fg_color.full << 16)) & 0x07E0F81F; + uint32_t result = ((((fg - bg) * factor) >> 5) + bg) & 0x7E0F81F; + ret.full = (uint16_t)((result >> 16) | result); + +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB888) + + ret.ch.red = bg_color.ch.red + ((fg_color.ch.red - bg_color.ch.red) * factor >> 8); + ret.ch.green = bg_color.ch.green + ((fg_color.ch.green - bg_color.ch.green) * factor >> 8); + ret.ch.blue = bg_color.ch.blue + ((fg_color.ch.blue - bg_color.ch.blue) * factor >> 8); + +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_ARGB8888) + + ret.ch.alpha = bg_color.ch.alpha + ((fg_color.ch.alpha - bg_color.ch.alpha) * factor >> 8); + ret.ch.red = bg_color.ch.red + ((fg_color.ch.red - bg_color.ch.red) * factor >> 8); + ret.ch.green = bg_color.ch.green + ((fg_color.ch.green - bg_color.ch.green) * factor >> 8); + ret.ch.blue = bg_color.ch.blue + ((fg_color.ch.blue - bg_color.ch.blue) * factor >> 8); + +#endif + return ret; +} + + +/** + * @brief Fills a block of memory with a solid color. + * + * Writes the specified `color` value to `len` consecutive elements starting at `dest`. + * This is equivalent to a memset-like operation but for color values (typically 32-bit RGBA). + * + * @param[out] dest Pointer to the start of the destination color buffer. + * @param[in] color The color value to fill with. + * @param[in] len Number of color elements to write (not bytes). + */ +static inline void sgl_color_set(sgl_color_t *dest, sgl_color_t color, uint32_t len) +{ + while (len--) {*dest++ = color; } +} + + +/** + * @brief area init + * @param area : area pointer + * @return none + */ +static inline void sgl_area_init(sgl_area_t *area) +{ + SGL_ASSERT(area != NULL); + area->x1 = area->y1 = SGL_POS_MAX; + area->x2 = area->y2 = SGL_POS_MIN; +} + + +/** + * @brief get pixel of pixmap + * @pixmap: pointe to pixmap + * @param x: x position + * @param y: y position + * @return sgl_color_t: pixel color + */ +static inline sgl_color_t sgl_pixmap_get_pixel(const sgl_pixmap_t *pixmap, int16_t x, int16_t y) +{ + SGL_ASSERT(pixmap != NULL); + return ((sgl_color_t*)pixmap->bitmap.array)[y * pixmap->width + x]; +} + + +/** + * @brief get pixel of pixmap buf + * @pixmap: pointe to pixmap + * @param x: x position + * @param y: y position + * @return sgl_color_t: pixel color address + */ +static inline sgl_color_t* sgl_pixmap_get_buf(const sgl_pixmap_t *pixmap, int16_t x, int16_t y) +{ + SGL_ASSERT(pixmap != NULL); + return &((sgl_color_t*)pixmap->bitmap.array)[y * pixmap->width + x]; +} + + +/** + * @brief check two area is overlap + * @param area_a area a + * @param area_b area b + * @return true or false, true means overlap, false means not overlap + * @note: this function is unsafe, you should check the area_a and area_b is not NULL by yourself + */ +static inline bool sgl_area_is_overlap(sgl_area_t *area_a, sgl_area_t *area_b) +{ + SGL_ASSERT(area_a != NULL && area_b != NULL); + if (area_b->y1 > area_a->y2 || area_b->y2 < area_a->y1 || area_b->x1 > area_a->x2 || area_b->x2 < area_a->x1) { + return false; + } + + return true; +} + + +/** + * @brief check surf and other area is overlap + * @param surf surfcare + * @param area area b + * @return true or false, true means overlap, false means not overlap + * @note: this function is unsafe, you should check the surfcare and area is not NULL by yourself + */ +static inline bool sgl_surf_area_is_overlap(sgl_surf_t *surf, sgl_area_t *area) +{ + return sgl_area_is_overlap((sgl_area_t*)surf, area); +} + + +/** + * @brief Get area intersection between two areas + * @param area_a: area a + * @param area_b: area b + * @param clip: intersection area + * @return true: intersect, otherwise false + * @note: this function is unsafe, you should check the area_a and area_b and clip is not NULL by yourself + */ +bool sgl_area_clip(sgl_area_t *area_a, sgl_area_t *area_b, sgl_area_t *clip); + + +/** + * @brief Get area intersection between surface and area + * @param surf: surface + * @param area: area + * @param clip: intersection area + * @return true: intersect, otherwise false + * @note: this function is unsafe, you should check the surf and area is not NULL by yourself + */ +static inline bool sgl_surf_clip(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *clip) +{ + return sgl_area_clip((sgl_area_t*)surf, area, clip); +} + + +/** + * @brief clip area with another area + * @param clip [in][out] clip area + * @param area [in] area + * @return true if clip area is valid, otherwise two area is not overlapped + * @note: this function is unsafe, you should check the clip and area is not NULL by yourself + */ +bool sgl_area_selfclip(sgl_area_t *clip, sgl_area_t *area); + + +/** + * @brief merge two area, the merge is result of the two area clip + * @param area_a [in] area1 + * @param area_b [in] area2 + * @param merge [out] merge result + * @return none + * @note: this function is unsafe, you should check the area_a and area_b and merge is not NULL by yourself + */ +static inline void sgl_area_merge(sgl_area_t *area_a, sgl_area_t *area_b, sgl_area_t *merge) +{ + SGL_ASSERT(area_a != NULL && area_b != NULL && merge != NULL); + merge->x1 = sgl_min(area_a->x1, area_b->x1); + merge->x2 = sgl_max(area_a->x2, area_b->x2); + merge->y1 = sgl_min(area_a->y1, area_b->y1); + merge->y2 = sgl_max(area_a->y2, area_b->y2); +} + + +/** + * @brief merge two area, the merge is a new area + * @param merge [in][out] merge area + * @param area [in] area + * @return none + * @note: this function is unsafe, you should check the merge and area is not NULL by yourself + */ +static inline void sgl_area_selfmerge(sgl_area_t *merge, sgl_area_t *area) +{ + SGL_ASSERT(merge != NULL && area != NULL); + merge->x1 = sgl_min(merge->x1, area->x1); + merge->x2 = sgl_max(merge->x2, area->x2); + merge->y1 = sgl_min(merge->y1, area->y1); + merge->y2 = sgl_max(merge->y2, area->y2); +} + + +/** + * @brief sgl global initialization + * @param none + * @return int, 0 means success, others means failed + * @note You should call this function before using sgl and you should call this function after register framebuffer device. + * This function is unsafe, you should check the return value by yourself. + */ +int sgl_init(void); + + +/** + * @brief initialize object + * @param obj object + * @param parent parent object + * @return int, 0 means successful, -1 means failed + */ +int sgl_obj_init(sgl_obj_t *obj, sgl_obj_t *parent); + + +/** + * @brief Convert UTF-8 string to Unicode + * @param utf8_str Pointer to the UTF-8 string to be converted + * @param p_unicode_buffer Pointer to the buffer where the converted Unicode will be stored + * @return The number of bytes in the UTF-8 string + */ +uint32_t sgl_utf8_to_unicode(const char *utf8_str, uint32_t *p_unicode_buffer); + + +/** + * @brief Search for the index of a Unicode character in the font table + * @param font Pointer to the font structure containing character data + * @param unicode Unicode of the character to be searched + * @return Index of the character in the font table + */ +uint32_t sgl_search_unicode_ch_index(const sgl_font_t *font, uint32_t unicode); + + +/** + * @brief get height in font + * @param font pointer to sgl_font_t + * @return height of font, -1 means error + * @note this function is used to get the height of a character in a font + */ +static inline int16_t sgl_font_get_height(const sgl_font_t *font) +{ + SGL_ASSERT(font != NULL); + return font->font_height; +} + + +/** + * @brief get the width of a string + * @param str string + * @param font sgl font + * @return width of string + */ +int32_t sgl_font_get_string_width(const char *str, const sgl_font_t *font); + + +/** + * @brief get the height of a string, which is in a rect area + * @param width width of the rect area + * @param str string + * @param font sgl font of the string + * @param line_space peer line space + * @return height size of string + */ +int32_t sgl_font_get_string_height(int16_t width, const char *str, const sgl_font_t *font, uint8_t line_space); + + +/** + * @brief get the alignment position + * @param parent_size parent size + * @param size object size + * @param type alignment type + * @return alignment position + */ +sgl_pos_t sgl_get_align_pos(sgl_size_t *parent_size, sgl_size_t *size, sgl_align_type_t type); + + +/** + * @brief get the text position in the area + * @param area point to area + * @param font point to font + * @param text text string + * @param offset text offset + * @param type alignment type + * @return sgl_pos_t position of text + */ +sgl_pos_t sgl_get_text_pos(sgl_area_t *area, const sgl_font_t *font, const char *text, int16_t offset, sgl_align_type_t type); + + +/** + * @brief get the icon position of area + * @param area point to area + * @param icon point to icon + * @param offset offset + * @param type align type + */ +sgl_pos_t sgl_get_icon_pos(sgl_area_t *area, const sgl_icon_pixmap_t *icon, int16_t offset, sgl_align_type_t type); + + +/** + * @brief set page background color + * @param obj point to object + * @param color background color + * @return none + */ +void sgl_page_set_color(sgl_obj_t* obj, sgl_color_t color); + + +/** + * @brief set page background pixmap + * @param obj point to object + * @param pixmap background pixmap + * @return none + */ +void sgl_page_set_pixmap(sgl_obj_t* obj, const sgl_pixmap_t *pixmap); + + +/** + * @brief set page background alpha + * @param obj point to object + * @param alpha background alpha + * @return none + */ +void sgl_page_set_alpha(sgl_obj_t* obj, uint8_t alpha); + + +/** + * @brief get parent of an object + * @param obj the object + * @return the parent of the object + */ +static inline sgl_obj_t* sgl_obj_get_parent(sgl_obj_t* obj) +{ + SGL_ASSERT(obj != NULL); + return obj->parent; +} + + +/** + * @brief format a string, a simple version of vsnprintf + * @param buf buffer + * @param size buffer size + * @param fmt format string + * @param ap argument list + * @return number of characters written + */ +int sgl_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap); + + +/** + * @brief format a string, a simple version of snprintf + * @param buf buffer + * @param size buffer size + * @param fmt format string + * @param ... arguments + * @return number of characters written + */ +int sgl_snprintf(char *buf, size_t size, const char *fmt, ...); + + +#if (CONFIG_SGL_OBJ_USE_NAME) +/** + * @brief set object name + * @param obj The object to set the name + * @param name The name to set. + * @return None. + */ +static inline void sgl_obj_set_name(sgl_obj_t *obj, const char *name) +{ + SGL_ASSERT(obj != NULL); + obj->name = name; +} + + +/** + * @brief print object name that include this all child + * @param obj point to object + * @return none + */ +void sgl_obj_print_name(sgl_obj_t *obj); + +#endif + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + + +#endif //__SGL_CORE_H__ diff --git a/User/system/sgl/include/sgl_draw.h b/User/system/sgl/include/sgl_draw.h new file mode 100644 index 0000000..718bc21 --- /dev/null +++ b/User/system/sgl/include/sgl_draw.h @@ -0,0 +1,513 @@ +/* source/include/sgl_draw.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_DRAW_H__ +#define __SGL_DRAW_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SGL_ARC_MODE_NORMAL (0) +#define SGL_ARC_MODE_RING (1) +#define SGL_ARC_MODE_NORMAL_SMOOTH (2) +#define SGL_ARC_MODE_RING_SMOOTH (3) + + +/** + * @brief rect description + * @color: color of rect + * @alpha: alpha of rect + * @border: border of rect + * @border_color: border color of rect + * @pixmap: pixmap of rect + */ +typedef struct sgl_draw_rect { + sgl_color_t color; + int16_t radius; + uint8_t alpha; + uint8_t border; + sgl_color_t border_color; + const sgl_pixmap_t *pixmap; +} sgl_draw_rect_t; + + +/** + * @brief line draw description + * @x1: x1 coordinate + * @y1: y1 coordinate + * @x2: x2 coordinate + * @y2: y2 coordinate + * @color: color + * @alpha: alpha + * @width: width of line + */ +typedef struct sgl_draw_line { + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; + sgl_color_t color; + uint8_t alpha; + uint8_t width; +} sgl_draw_line_t; + + +/** + * @brief rectangle description + * @cx: center x of rectangle + * @cy: center y of rectangle + * @color: color of rectangle + * @radius: radius of rectangle + * @alpha: alpha of rectangle + * @border: border of rectangle + * @border_color: border color of rectangle + * @pixmap: pixmap of rectangle + */ +typedef struct sgl_draw_circle { + int16_t cx; + int16_t cy; + sgl_color_t color; + int16_t radius; + uint8_t alpha; + uint8_t border; + sgl_color_t border_color; + const sgl_pixmap_t *pixmap; +} sgl_draw_circle_t; + + +/** + * @brief arc description + * @cx: center x + * @cy: center y + * @radius_in: inner radius of arc + * @radius_out: outer radius of arc + * @start_angle: start angle of arc + * @end_angle: end angle of arc + * @color: color of arc + * @alpha: alpha of arc + * @mode: mode of arc + * @bg_color: background color of arc + */ +typedef struct sgl_draw_arc { + int16_t cx; + int16_t cy; + int16_t radius_in; + int16_t radius_out; + sgl_color_t color; + uint8_t alpha; + uint32_t start_angle: 9; + uint32_t end_angle: 9; + uint32_t mode: 2; + sgl_color_t bg_color; +} sgl_draw_arc_t; + + +/** + * @brief icon description + * @icon: icon pixmap + * @color: icon color + * @alpha: alpha of icon + */ +typedef struct sgl_draw_icon { + const sgl_icon_pixmap_t *icon; + sgl_color_t color; + uint8_t alpha; + uint8_t align; +} sgl_draw_icon_t; + + +/** + * @brief clip area width of surface + * @note if you want to check the area is overlap with surface, you can use this macro + * it will direct return if the area is not overlap with surface, otherwise, continue + */ +#if (CONFIG_SGL_USE_FBDEV_VRAM) +#define sgl_surf_clip_area_return(surf, rect, clip) do {SGL_UNUSED(rect);} while(0) +#else +#define sgl_surf_clip_area_return(surf, rect, clip) if (!sgl_surf_clip(surf, rect, clip)) return +#endif + + +/** + * @brief set pixel on surface + * @param surf: pointer of surface + * @param x: x coordinate + * @param y: y coordinate + * @param color: color of pixel + * @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface. + */ +static inline void sgl_surf_set_pixel(sgl_surf_t *surf, int16_t x, int16_t y, sgl_color_t color) +{ + surf->buffer[y * surf->w + x] = color; +} + + +/** + * @brief get start buffer address that to set pixel on surface + * @param surf: pointer of surface + * @param x: x coordinate + * @param y: y coordinate + * @return pointer of start buffer address + * @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface. + */ +static inline sgl_color_t* sgl_surf_get_buf(sgl_surf_t *surf, int16_t x, int16_t y) +{ + return &surf->buffer[y * surf->w + x]; +} + + +/** + * @brief get pixel on surface + * @param surf: pointer of surface + * @param x: x coordinate + * @param y: y coordinate + * @return color of pixel + * @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface. + */ +static inline sgl_color_t sgl_surf_get_pixel(sgl_surf_t *surf, int16_t x, int16_t y) +{ + return surf->buffer[y * surf->w + x]; +} + + +/** + * @brief draw a horizontal line on surface + * @param surf: pointer of surface + * @param y: y coordinate + * @param x1: x1 coordinate + * @param x2: x2 coordinate + * @param color: color of line + * @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface. + */ +static inline void sgl_surf_hline(sgl_surf_t *surf, int16_t y, int16_t x1, int16_t x2, sgl_color_t color) +{ + sgl_color_t *dst = surf->buffer + y * surf->w + x1; + for (int16_t i = x1; i <= x2; i++) { + *dst = color; + dst++; + } +} + + +/** + * @brief draw a vertical line on surface + * @param surf: pointer of surface + * @param x: x coordinate + * @param y1: y1 coordinate + * @param y2: y2 coordinate + * @param color: color of line + * @note this function is not clip, you should clip it before call this function, and the coordinate should be in the surface. + */ +static inline void sgl_surf_vline(sgl_surf_t *surf, int16_t x, int16_t y1, int16_t y2, sgl_color_t color) +{ + sgl_color_t *dst = surf->buffer + y1 * surf->w + x; + for (int16_t i = y1; i <= y2; i++) { + *dst = color; + dst += surf->w; + } +} + + +/** + * @brief fill a round rectangle with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param color color of rectangle + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, uint8_t alpha); + + +/** + * @brief fill a round rectangle with alpha and border + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param color color of rectangle + * @param border_color color of border + * @param border_width width of border + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect_with_border(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, sgl_color_t color, sgl_color_t border_color, uint8_t border_width, uint8_t alpha); + + +/** + * @brief fill a round rectangle pixmap with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param radius radius of round + * @param pixmap pixmap of rectangle + * @param alpha alpha of rectangle + * @return none + */ +void sgl_draw_fill_rect_pixmap(sgl_surf_t *surf, sgl_area_t *area, sgl_area_t *rect, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha); + + +/** + * @brief fill a round rectangle with alpha + * @param surf point to surface + * @param area area of rectangle that you want to draw + * @param rect point to rectangle that you want to draw + * @param desc rectangle description + * @return none + */ +void sgl_draw_rect(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *rect, sgl_draw_rect_t *desc); + + +/** + * @brief Draw a circle + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param color Color of the circle + * @param alpha Alpha of the circle + * @return none + */ +void sgl_draw_fill_circle(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, uint8_t alpha); + + +/** + * @brief Draw a circle with pixmap and alpha + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param pixmap Pixmap of image + * @param alpha Alpha of the circle + * @return none + */ +void sgl_draw_fill_circle_pixmap(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, const sgl_pixmap_t *pixmap, uint8_t alpha); + + +/** + * @brief Draw a circle with alpha and border + * @param surf Surface + * @param area Area of the circle + * @param cx X coordinate of the center + * @param cy Y coordinate of the center + * @param radius Radius of the circle + * @param color Color of the circle + * @param border_color Color of the border + * @param border_width Width of the border + * @param alpha Alpha of the circle + * @return none + */ + +void sgl_draw_fill_circle_with_border(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius, sgl_color_t color, sgl_color_t border_color, int16_t border_width, uint8_t alpha); + + +/** + * @brief draw task, the task contains the draw information and canvas + * @param surf surface pointer + * @param area the area of the task + * @param desc the draw information + * @return none + */ +void sgl_draw_circle(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_circle_t *desc); + + +/** + * @brief draw icon with alpha + * @param surf surface + * @param area area of icon + * @param coords coords of icon + * @param icon icon pixmap + * @param alpha alpha of icon + */ +void sgl_draw_icon( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, sgl_color_t color, uint8_t alpha, const sgl_icon_pixmap_t *icon); + + +/** + * @brief Draw a character on the surface with alpha blending + * @param surf Pointer to the surface where the character will be drawn + * @param area Pointer to the area where the character will be drawn + * @param x X coordinate where the character will be drawn + * @param y Y coordinate where the character will be drawn + * @param ch_index Index of the character in the font table + * @param color Foreground color of the character + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @return none + * @note this function is only support bpp:4 + */ +void sgl_draw_character( sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, uint32_t ch_index, sgl_color_t color, uint8_t alpha, const sgl_font_t *font); + + +/** + * @brief Draw a string on the surface with alpha blending + * @param surf Pointer to the surface where the string will be drawn + * @param area Pointer to the area where the string will be drawn + * @param x X coordinate of the top-left corner of the string + * @param y Y coordinate of the top-left corner of the string + * @param str Pointer to the string to be drawn + * @param color Foreground color of the string + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @return none + */ +void sgl_draw_string(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font); + + +/** + * @brief Draw a string on the surface with alpha blending and multiple lines + * @param surf Pointer to the surface where the string will be drawn + * @param area Pointer to the area where the string will be drawn + * @param x X coordinate of the top-left corner of the string + * @param y Y coordinate of the top-left corner of the string + * @param str Pointer to the string to be drawn + * @param color Foreground color of the string + * @param alpha Alpha value for blending + * @param font Pointer to the font structure containing character data + * @param line_margin Margin between lines + * @return none + */ +void sgl_draw_string_mult_line(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y, const char *str, sgl_color_t color, uint8_t alpha, const sgl_font_t *font, uint8_t line_margin); + + +/** + * @brief draw a ring on surface with alpha + * @param surf: pointer of surface + * @param area: pointer of area + * @param cx: ring center x + * @param cy: ring center y + * @param radius_in: ring inner radius + * @param radius_out: ring outer radius + * @param color: ring color + * @param alpha: ring alpha + * @return none + */ +void sgl_draw_fill_ring(sgl_surf_t *surf, sgl_area_t *area, int16_t cx, int16_t cy, int16_t radius_in, int16_t radius_out, sgl_color_t color, uint8_t alpha); + + +/** + * @brief draw a horizontal line with alpha + * @param surf surface + * @param area area that contains the line + * @param y line y position + * @param x1 line start x position + * @param x2 line end x position + * @param color line color + * @param alpha alpha of color + * @return none + */ +void sgl_draw_fill_hline(sgl_surf_t *surf, sgl_area_t *area, int16_t y, int16_t x1, int16_t x2, uint8_t width, sgl_color_t color, uint8_t alpha); + + +/** + * @brief draw a vertical line with alpha + * @param surf surface + * @param area area that contains the line + * @param x x coordinate + * @param y1 y1 coordinate + * @param y2 y2 coordinate + * @param color line color + * @param alpha alpha of color + * @return none + */ +void sgl_draw_fill_vline(sgl_surf_t *surf, sgl_area_t *area, int16_t x, int16_t y1, int16_t y2, uint8_t width, sgl_color_t color, uint8_t alpha); + + +/** + * @brief draw a slanted line with alpha + * @param surf surface + * @param area area that contains the line + * @param x1 line start x position + * @param y1 line start y position + * @param x2 line end x position + * @param y2 line end y position + * @param thickness line width + * @param color line color + * @param alpha alpha of color + * @return none + * @note This algorithm is SDF algorithm + */ +void draw_line_fill_slanted(sgl_surf_t *surf, sgl_area_t *area, int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t thickness, sgl_color_t color, uint8_t alpha); + + +/** + * @brief draw a line + * @param surf surface + * @param area area that contains the line + * @param desc line description + * @return none + */ +void sgl_draw_line(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_line_t *desc); + + +/** + * @brief draw an arc with alpha + * @param surf pointer to surface + * @param area pointer to area + * @param desc pointer to arc description + * @return none + */ +void sgl_draw_fill_arc(sgl_surf_t *surf, sgl_area_t *area, sgl_draw_arc_t *desc); + + +/** + * @brief calculate a point color by bilinear interpolate + * @param buffer point to image pixmap start buffer + * @param w width of buffer + * @param h height of buffer + * @param fx x coordinate of point + * @param fy y coordinate of point + * @return point color + */ +sgl_color_t sgl_draw_biln_color(const sgl_color_t *buffer, int16_t w, int16_t h, int32_t fx, int32_t fy); + + +/** + * @brief transform a surface + * @param dst destination surface + * @param src source surface + * @param area area of surface + * @param x x coordinate of surface + * @param y y coordinate of surface + * @param rotation rotation angle + * @return none + * @note This function has implemented angle normalization to the range of 0 to 360 degrees. + */ +void sgl_draw_xform_surf(sgl_surf_t *dst, sgl_surf_t *src, sgl_area_t *area, int16_t x, int16_t y, int16_t rotation); + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif diff --git a/User/system/sgl/include/sgl_errno.h b/User/system/sgl/include/sgl_errno.h new file mode 100644 index 0000000..9bc1f1d --- /dev/null +++ b/User/system/sgl/include/sgl_errno.h @@ -0,0 +1,170 @@ +/* source/include/sgl_errno.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __SGL_ERRNO_H__ +#define __SGL_ERRNO_H__ + +#define OK 0 /* No error */ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ + +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ +#define ERFKILL 132 /* Operation not possible due to RF-kill */ +#define EHWPOISON 133 /* Memory page has hardware error */ + +#endif // !__SGL_ERRNO_H__ diff --git a/User/system/sgl/include/sgl_event.h b/User/system/sgl/include/sgl_event.h new file mode 100644 index 0000000..7097e8d --- /dev/null +++ b/User/system/sgl/include/sgl_event.h @@ -0,0 +1,220 @@ +/* source/include/sgl_event.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_EVENT_H__ +#define __SGL_EVENT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include +#include +#include + + +/* Forward declaration of sgl_obj and sgl_page*/ +struct sgl_obj; +struct sgl_page; + + +/** + * @brief Event type enumeration + * @note The event type is used to describe the type of event, such as click, + * long press, etc. The event type is used to distinguish different events, + * and the event type is used to trigger different callbacks + */ +#define SGL_EVENT_NULL (0) +#define SGL_EVENT_NORMAL (1) +#define SGL_EVENT_PRESSED (2) +#define SGL_EVENT_RELEASED (3) +#define SGL_EVENT_CLICKED (4) +#define SGL_EVENT_LONG_CLICKED (5) +#define SGL_EVENT_MOTION (6) +#define SGL_EVENT_MOVE_UP (7) +#define SGL_EVENT_MOVE_DOWN (8) +#define SGL_EVENT_MOVE_LEFT (9) +#define SGL_EVENT_MOVE_RIGHT (10) +#define SGL_EVENT_LONG_PRESSED (11) +#define SGL_EVENT_OPTION_WALK (12) +#define SGL_EVENT_OPTION_TAP (13) +#define SGL_EVENT_DRAW_INIT (14) +#define SGL_EVENT_DRAW_MAIN (15) +#define SGL_EVENT_FOCUSED (16) +#define SGL_EVENT_UNFOCUSED (17) +#define SGL_EVENT_DESTROYED (18) +#define sgl_event_type_t uint8_t + + +#define SGL_EVENT_CLICK_INTERVAL (CONFIG_SGL_EVENT_CLICK_INTERVAL) + +/** +* @brief Event location structure, Used to represent the coordinates of an event, +* such as the click position of the mouse, the click position of the touch screen, +* and so on +* +* @x: x coordinate +* @y: y coordinate +*/ +typedef struct sgl_event_pos { + int16_t x; + int16_t y; +} sgl_event_pos_t; + + +typedef struct sgl_event { + struct sgl_obj *obj; + void *param; + sgl_event_pos_t pos; + uint16_t type; + uint16_t distance; +} sgl_event_t; + + +/** + * @brief Initialize the event queue + * @param none + * @return 0 on success, -1 on failure + * @note !!!!!! the SGL_EVENT_QUEUE_SIZE must be power of 2 !!!!!! + * You must check the return value of this function. + */ +int sgl_event_queue_init(void); + + +/** + * @brief Push an event into the event queue + * @param event The event to be pushed + * @return 0 on success, -1 on failure + */ +void sgl_event_queue_push(sgl_event_t event); + + +/** + * @brief Handle the position event + * @param pos The position to be handled + * @param type The type of the event + * @return none + */ +void sgl_event_send_pos(sgl_event_pos_t pos, sgl_event_type_t type); + + +/** + * @brief Send an event to the specified object + * @param event The event to be sent + * @return none + */ +static inline void sgl_event_send(sgl_event_t event) +{ + sgl_event_queue_push(event); +} + + +/** + * @brief Send an event to the specified object + * @param obj The object to be sent + * @param type The type of the event + * @return none + * @note This function is used to send an event to the specified object, for example, + * if you want to send an event to the button, you can call: + * ---- press button case : sgl_event_send_obj(button, SGL_EVENT_PRESSED); + * ---- release button case: sgl_event_send_obj(button, SGL_EVENT_RELEASED); + * + * @tip: You can also send you own event to the specified object, for example, + * The MY_EVENT_TYPE is defined by you, and you can use it in your own event handler, for example: + * ... + * sgl_event_send_obj(button, MY_EVENT_TYPE); + * ... + * void my_event_handler(sgl_event_t *event) + * { + * if (event->type == MY_EVENT_TYPE) { + * // do something + * } + * } + */ +static inline void sgl_event_send_obj(struct sgl_obj *obj, sgl_event_type_t type) +{ + sgl_event_t event = {0}; + event.obj = obj; + event.type = type; + sgl_event_send(event); +} + + +/** + * @brief Send a motion event to the specified object + * @param pos The position of the motion event + * @param type The type of the motion event + * @param distance The distance of the motion event + * @return none + */ +static inline void sgl_event_send_motion(sgl_event_pos_t pos, sgl_event_type_t type, uint16_t distance) +{ + sgl_event_t event = {0}; + event.pos = pos; + event.type = type; + event.distance = distance; + sgl_event_send(event); +} + + +/** + * @brief All event task in SGL, this function will traverse all elements in the event queue, + * respond to each element with an event, so that all events will trigger and point to the + * corresponding callback function + * @param none + * @return none +*/ +void sgl_event_task(void); + + +/** + * @brief Touch event read, this function will be called by user + * @param x: touch x position + * @param y: touch y position + * @param flag: touch flag, it means touch event down or up: + * true : touch down + * false: touch up + * @return none + * @note: for example, you can call it in 30ms tick handler function + * void example_30ms_tick_handler(void) + * { + * int pos_x, pos_y; + * bool button_status; + * + * bsp_touch_read_pos(&pos_x, &pos_y); + * button_status = bsp_touch_read_status(); + * + * sgl_event_pos_input(pos_x, pos_y, button_status); + * } + */ +void sgl_event_pos_input(int16_t x, int16_t y, bool flag); + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif //!__SGL_EVENT_H__ diff --git a/User/system/sgl/include/sgl_font.h b/User/system/sgl/include/sgl_font.h new file mode 100644 index 0000000..9775a4e --- /dev/null +++ b/User/system/sgl/include/sgl_font.h @@ -0,0 +1,66 @@ +/* source/include/sgl_font.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#ifndef __SGL_FONT_H__ +#define __SGL_FONT_H__ + + +#include +#include +#include +#include +#include + +/* declare all font */ + +#if CONFIG_SGL_FONT_SONG23 +extern const sgl_font_t song23; +#endif + +#if CONFIG_SGL_FONT_CONSOLAS14 +extern const sgl_font_t consolas14; +#endif + +#if CONFIG_SGL_FONT_CONSOLAS23 +extern const sgl_font_t consolas23; +#endif + +#if CONFIG_SGL_FONT_CONSOLAS24 +extern const sgl_font_t consolas24; +#endif + +#if CONFIG_SGL_FONT_CONSOLAS32 +extern const sgl_font_t consolas32; +#endif + +#if CONFIG_SGL_FONT_KAI33 +extern const sgl_font_t kai33; +#endif + +#if CONFIG_SGL_FONT_CONSOLAS24_COMPRESS +extern const sgl_font_t consolas24_compress; +#endif + +#endif // !__SGL_FONT_H__ diff --git a/User/system/sgl/include/sgl_list.h b/User/system/sgl/include/sgl_list.h new file mode 100644 index 0000000..7bb08dd --- /dev/null +++ b/User/system/sgl/include/sgl_list.h @@ -0,0 +1,307 @@ +/* source/include/sgl_list.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LIST_H__ +#define __SGL_LIST_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include + + +/** + * @prev: previous node of the list. + * @next: next node of the list. + */ +typedef struct sgl_list_node { + struct sgl_list_node *prev; + struct sgl_list_node *next; +}sgl_list_node_t; + +#define SGL_LIST_HEAD(name) \ + sgl_list_node_t name = {.prev = &(name), .next = &(name)} + + +/** + * @brief foreach the list. + * + * @pos: the &struct list_head to use as a loop cursor. + * @list_head: the head for your list. + * + * @return none + */ +#define sgl_list_for_each(pos, list_head) \ + for (pos = (list_head)->next; pos != (list_head); pos = pos->next) + + +/** + * @brief Return the next entry of specific node. + * + * @entry: specific entry. + * + * @return entry_type: next entry of specific entry. + */ +#define sgl_list_next_entry(entry, entry_type, list_node_member) \ + sgl_container_of(entry->list_node_member.next, entry_type, list_node_member) + + +/** + * @brief Return the previous entry of specific node. + * + * @entry: specific entry. + * + * @return entry_type: previous entry of specific entry. + */ +#define sgl_list_prev_entry(entry, entry_type, list_node_member) \ + sgl_container_of(entry->list_node_member.prev, entry_type, list_node_member) + + +/** + * @brief foreach the list inserted in a structure. + * + * @pos: the &struct list_head to use as a loop cursor. + * @list_head: the head for your list. + * @entry_type: type of the struct. + * @list_node_member: member name of the list_node in structure. + * + * @return none + */ +#define sgl_list_for_each_entry(pos, list_head, entry_type, list_node_member) \ + for (pos = sgl_container_of((list_head)->next, entry_type, list_node_member); \ + &pos->list_node_member != (list_head); \ + pos = sgl_container_of(pos->list_node_member.next, entry_type, list_node_member)) + + +/** + * @brief safe foreach the list inserted in a structure. + * + * @pos: the &struct list_head to use as a loop cursor. + * @list_head: the head for your list. + * @entry_type: type of the struct. + * @list_node_member: member name of the list_node in structure. + * + * @return none + */ +#define sgl_list_for_each_entry_safe(pos, n, list_head, entry_type, list_node_member) \ + for (pos = (list_head)->next ? sgl_container_of((list_head)->next, entry_type, list_node_member) : NULL, \ + n = pos ? sgl_container_of(pos->list_node_member.next, entry_type, list_node_member) : NULL; \ + &pos->list_node_member != (list_head); \ + pos = n, \ + n = pos ? (pos->list_node_member.next ? sgl_container_of(pos->list_node_member.next, entry_type, list_node_member) : NULL) : NULL) + + +/** + * @brief reverse foreach the list inserted in a structure. + * + * @pos: the &struct list_head to use as a loop cursor. + * @list_head: the head for your list. + * @entry_type: type of the struct. + * @list_node_member: member name of the list_node in structure. + * + * @return none + */ +#define sgl_list_for_each_entry_reverse(pos, list_head, entry_type, list_node_member) \ + for (pos = sgl_container_of((list_head)->prev, entry_type, list_node_member); \ + &pos->list_node_member != (list_head); \ + pos = sgl_container_of(pos->list_node_member.prev, entry_type, list_node_member)) + + +/** + * @brief initialize a list. + * + * @node: inserted node. + * + * @return none + */ +static inline void sgl_list_init(sgl_list_node_t *node) +{ + node->next = node; + node->prev = node; +} + + +/** + * @brief Add a node to the list tail. + * + * @head: head node of the list. + * @node: inserted node. + * + * @return none + */ +static inline void sgl_list_add_node_at_tail(sgl_list_node_t *head, sgl_list_node_t *node) +{ + sgl_list_node_t *tail = head->prev; + + node->prev = tail; + node->next = head; + tail->next = node; + head->prev = node; +} + + +/** + * @brief Add a node to the list front. + * + * @head: head node of the list. + * @node: inserted node. + * + * @return none + */ +static inline void sgl_list_add_node_at_front(sgl_list_node_t *head, sgl_list_node_t *node) +{ + sgl_list_node_t *front = head->next; + + node->prev = head; + node->next = front; + front->prev = node; + head->next = node; +} + + +/** + * @brief Add a node to the list before a specific node. + * @pos: specific node. + * @node: inserted node. + * @return none + */ +static inline void sgl_list_add_node_at_before(sgl_list_node_t *pos, sgl_list_node_t *node) +{ + node->prev = pos->prev; + node->next = pos; + pos->prev->next = node; + pos->prev = node; +} + + +/** + * @brief Add a node to the list after a specific node. + * @pos: specific node. + * @node: inserted node. + * @return none + */ +static inline void sgl_list_add_node_at_after(sgl_list_node_t *pos, sgl_list_node_t *node) +{ + node->next = pos->next; + node->prev = pos; + pos->next->prev = node; + pos->next = node; +} + + +/** + * @brief Delete a tail node from the list. + * + * @head: head node of the list. + * + * @return none + */ +static inline void sgl_list_del_tail_node(sgl_list_node_t *head) +{ + sgl_list_node_t *tail_prev = head->prev->prev; + + tail_prev->next = head; + head->prev = tail_prev; +} + + +/** + * @brief Delete a front node from the list. + * + * @head: head node of the list. + * + * @return none + */ +static inline void sgl_list_del_front_node(sgl_list_node_t *head) +{ + sgl_list_node_t *front_next = head->next->next; + + front_next->prev = head; + head->next = front_next; +} + + +/** + * @brief Delete a node from the list. + * + * @node: the node of the list. + * + * @return none + */ +static inline void sgl_list_del_node(sgl_list_node_t *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; +} + + +/** + * @brief Determine whether the list is empty. + * + * @head: head node of the list. + * + * @return bool: is empty. + */ +static inline bool sgl_list_is_empty(sgl_list_node_t *head) +{ + return head->next == head; +} + + +/** + * @brief Return the next node of specific node. + * + * @node: specific node. + * + * @return list_node*: next node of specific node. + */ +static inline sgl_list_node_t* sgl_list_next_node(sgl_list_node_t *node) +{ + return node->next; +} + + +/** + * @brief Return the previous node of specific node. + * + * @node: specific node. + * + * @return list_node*: previous node of specific node. + */ +static inline sgl_list_node_t* sgl_list_prev_node(sgl_list_node_t *node) +{ + return node->prev; +} + + +#ifdef __cplusplus +} +#endif + + +#endif // __SGL_LIST_H__ diff --git a/User/system/sgl/include/sgl_log.h b/User/system/sgl/include/sgl_log.h new file mode 100644 index 0000000..569f7d4 --- /dev/null +++ b/User/system/sgl/include/sgl_log.h @@ -0,0 +1,193 @@ +/* source/include/sgl_log.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LOG_H__ +#define __SGL_LOG_H__ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SGL_LOG_LEVEL_TRACE 0 /**< A lot of logs to give detailed information*/ +#define SGL_LOG_LEVEL_INFO 1 /**< Log important events*/ +#define SGL_LOG_LEVEL_WARN 2 /**< Log if something unwanted happened but didn't caused problem*/ +#define SGL_LOG_LEVEL_ERROR 3 /**< Only critical issue, when the system may fail*/ +#define SGL_LOG_LEVEL_USER 4 /**< Custom logs from the user*/ +#define SGL_LOG_LEVEL_NONE 5 /**< Do not log anything*/ +#define _SGL_LOG_LEVEL_NUM 6 /**< Number of log levels*/ + + +#if CONFIG_SGL_DEBUG + +/** + * @brief sgl log printing function, used to print debugging information. Note that this function + * should only be called in debugging mode, otherwise it may affect system real-time + * performance due to long execution time + * + * @param level: log level, such as, INFO, USER... + * @param format: log content + * + * @return none +*/ +void sgl_log(const char *level, const char * format, ...); + + +/** + * @brief sgl assert handler, used to handle assertions + * + * @param file: file name + * @param func: function name + * @param line: line number + * + * @return none +*/ +void sgl_assert_handler(const char *file, const char *func, int line); + + +#if CONFIG_SGL_LOG_COLOR + +#define SGL_LOG_NONE "\033[0m" +#define SGL_LOG_RED "\033[31m" +#define SGL_LOG_GREEN "\033[32m" +#define SGL_LOG_YELLOW "\033[33m" +#define SGL_LOG_BLUE "\033[34m" +#define SGL_LOG_PURPLE "\033[35m" +#define SGL_LOG_CYAN "\033[36m" +#define SGL_LOG_WHITE "\033[37m" +#define SGL_LOG_LIGHT_BLUE "\033[1;34m" + + +#define SGL_LOG_TRACE_FLAG SGL_LOG_BLUE"[TRACE]" +#define SGL_LOG_INFO_FLAG SGL_LOG_GREEN"[INFO]" +#define SGL_LOG_WARN_FLAG SGL_LOG_YELLOW"[WARN]" +#define SGL_LOG_ERROR_FLAG SGL_LOG_RED"[ERROR]" +#define SGL_LOG_USER_FLAG SGL_LOG_PURPLE"[USER]" +#define SGL_ASSERT_FLAG SGL_LOG_CYAN"[ASSERT]" +#define SGL_DEBUG_TRACE_FLAG SGL_LOG_LIGHT_BLUE"[DEBUG]" + + +#else +#define SGL_LOG_TRACE_FLAG "[TRACE] " +#define SGL_LOG_INFO_FLAG "[INFO] " +#define SGL_LOG_WARN_FLAG "[WARN] " +#define SGL_LOG_ERROR_FLAG "[ERROR] " +#define SGL_LOG_USER_FLAG "[USER] " +#define SGL_ASSERT_FLAG "[ASSERT] " +#define SGL_DEBUG_TRACE_FLAG "[DEBUG]" +#define SGL_LOG_NONE "" + +#endif // !CONFIG_SGL_LOG_COLOR + + +#ifndef SGL_LOG_TRACE +# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_TRACE +# define SGL_LOG_TRACE(...) sgl_log(SGL_LOG_TRACE_FLAG, __VA_ARGS__) +# else +# define SGL_LOG_TRACE(...) do {} while(0) +# endif +#endif + +#ifndef SGL_LOG_INFO +# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_INFO +# define SGL_LOG_INFO(...) sgl_log(SGL_LOG_INFO_FLAG, __VA_ARGS__) +# else +# define SGL_LOG_INFO(...) do {} while(0) +# endif +#endif + +#ifndef SGL_LOG_WARN +# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_WARN +# define SGL_LOG_WARN(...) sgl_log(SGL_LOG_WARN_FLAG, __VA_ARGS__) +# else +# define SGL_LOG_WARN(...) do {} while(0) +# endif +#endif + +#ifndef SGL_LOG_ERROR +# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_ERROR +# define SGL_LOG_ERROR(...) sgl_log(SGL_LOG_ERROR_FLAG, __VA_ARGS__) +# else +# define SGL_LOG_ERROR(...) do {} while(0) +# endif +#endif + +#ifndef SGL_LOG_USER +# if CONFIG_SGL_LOG_LEVEL <= SGL_LOG_LEVEL_USER +# define SGL_LOG_USER(...) sgl_log(SGL_LOG_USER_FLAG, __VA_ARGS__) +# else +# define SGL_LOG_USER(...) do {} while(0) +# endif +#endif + +#if CONFIG_SGL_LOG_LEVEL < SGL_LOG_LEVEL_NONE +# define SGL_LOG(...) sgl_log(__VA_ARGS__) +#else +# define SGL_LOG(...) do {} while(0) +#endif + + +#define SGL_ASSERT(cond) do { \ + if (!(cond)) { \ + sgl_assert_handler(__FILE__, __FUNCTION__, __LINE__); \ + } \ + } while(0) + +#define SGL_ASSERT_INFO(cond, info) do { \ + if (!(cond)) { \ + SGL_LOG_ERROR("ASSERT: %s", info); \ + sgl_assert_handler(__FILE__, __FUNCTION__, __LINE__); \ + } \ + } while(0) + +#else // if no define debug mode macro + +#define SGL_LOG_NONE 0 +#define SGL_LOG_TRACE(...) do {} while(0) +#define SGL_LOG_INFO(...) do {} while(0) +#define SGL_LOG_WARN(...) do {} while(0) +#define SGL_LOG_ERROR(...) do {} while(0) +#define SGL_LOG_USER(...) do {} while(0) +#define SGL_LOG(...) do {} while(0) + +#define SGL_ASSERT(cond) do {} while(0) +#define SGL_ASSERT_INFO(cond, info) do {} while(0) +#endif + + +#if CONFIG_SGL_DEBUG +#define SGL_DEBUG_TRACE(...) sgl_log(SGL_DEBUG_TRACE_FLAG, __VA_ARGS__) +#else +#define SGL_DEBUG_TRACE(...) do {} while(0) +#endif + + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif //!__SGL_LOG_H__ diff --git a/User/system/sgl/include/sgl_math.h b/User/system/sgl/include/sgl_math.h new file mode 100644 index 0000000..9252ae7 --- /dev/null +++ b/User/system/sgl/include/sgl_math.h @@ -0,0 +1,188 @@ +/* source/include/sgl_math.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_MATH_H__ +#define __SGL_MATH_H__ + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define sgl_min(a, b) ((a) < (b) ? (a) : (b)) +#define sgl_min3(a, b, c) (sgl_min(sgl_min((a), (b)), (c))) +#define sgl_min4(a, b, c, d) (sgl_min(sgl_min((a), (b)), sgl_min((c), (d)))) + + +#define sgl_max(a, b) ((a) > (b) ? (a) : (b)) +#define sgl_max3(a, b, c) (sgl_max(sgl_max((a), (b)), (c))) +#define sgl_max4(a, b, c, d) (sgl_max(sgl_max((a), (b)), sgl_max((c), (d)))) + +#define sgl_clamp(val, min, max) (sgl_max(min, (sgl_min((val), (max))))) + +#define sgl_abs(x) ((x) > 0 ? (x) : (- (x))) + +#define sgl_pow2(x) ((x) * (x)) +#define sgl_pow3(x) ((x) * (x) * (x)) +#define sgl_pow4(x) ((x) * (x) * (x) * (x)) + +#define sgl_is_pow2(x) (((x) & ((x) - 1)) == 0) +#define sgl_is_even(x) (((x) & 1) == 0) +#define sgl_is_odd(x) ((x) & 1) + +#define sgl_swap(a, b) do { (*a) ^= (*b); (*b) ^= (*a); (*a) ^= (*b); } while (0) + +#define sgl_mid(a, b) (((a) + (b)) / 2) + +#define SGL_FIXED_SHIFT (10) +#define SGL_FIXED_ONE (1 << SGL_FIXED_SHIFT) +#define SGL_FIXED_MASK (SGL_FIXED_ONE - 1) + +#define SGL_SIN_FIXED_ONE (32767) +#define SGL_COS_FIXED_ONE (32767) + +/** + * @brief Calculate the sine of an angle + * @param angle: Angle in degrees such 0-359 + * @return sine of the angle from sin0_90_table + * @note This function has implemented angle normalization to the range of 0 to 360 degrees. + */ +int32_t sgl_sin(int16_t angle); + + +/** + * @brief Calculate the cos of an angle + * @param angle: Angle in degrees such 0-359 + * @return cos of the angle from sin0_90_table + * @note This function has implemented angle normalization to the range of 0 to 360 degrees. + */ +static inline int32_t sgl_cos(int16_t angle) +{ + return sgl_sin(angle + 90); +} + + +/** + * @brief Calculate x number square root + * @param x: x number + * @retval x number square root + */ +uint16_t sgl_sqrt(uint32_t x); + + +/** + * @brief Calculate error of the square root for a number. + * @param x The number to calculate the error for. + * @return The error of the square root. [0 ~ 255] + */ +uint8_t sgl_sqrt_error(uint32_t x); + + +/** + * @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm + * implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm) + * + * @param x: The x coordinate on a circle + * @param y: The y coordinate on a circle + * @return angle + * @note return angle [-32767 ~ 32767] + */ +int32_t sgl_atan2_raw(int x, int y); + + +/** + * @brief Calculate the angle based on the x and y coordinates. This function is a fast algorithm + * implementation, with reference address: www.RomanBlack.com (Fast XY vector to integer degree algorithm) + * + * @param x: The x coordinate on a circle + * @param y: The y coordinate on a circle + * @return angle + * @note return angle [0 ~ 359] +*/ +uint16_t sgl_atan2_angle(int x, int y); + + +/** + * @brief Split the length into n parts, with the weight of each part. + * @param weight: The weight of each part. + * @param count: The count of parts. + * @param length: The length to split. + * @param gap: The gap between each part. + * @param out: The length of each part. + * @note The error accumulation method of Bresenham's algorithm + */ +void sgl_split_len(const uint8_t *weight, int count, int16_t length, int16_t gap, int16_t *out); + + +/** + * @brief Split the length into n parts, with the weight of each part. + * @param length: The length to split. + * @param count: The count of parts. + * @param gap: The gap between each part. + * @param out: The length of each part. + * @note The average method of Bresenham's algorithm + */ +void sgl_split_len_avg(int length, int count, int16_t gap, int16_t *out); + + +/** + * @brief Calculate whether the x and y coordinates have a component. + * @param x: The x coordinate on a circle + * @param y: The y coordinate on a circle + * @param xv: The x coordinate of the vector + * @param yv: The y coordinate of the vector + * @return 1: The x and y coordinates have a component. 0: The x and y coordinates do not have a component. + */ +static inline int sgl_xy_has_component( int x, int y, int xv, int yv) +{ + return ((x != 0 && ((xv ^ x) < 0)) || (y != 0 && ((yv ^ y) < 0))); +} + + +/** + * @brief Generate a random number. + * @param none + * @return Random number. + * @note The random number generator is in the range of [0, 32767]. + */ +int16_t sgl_rand(void); + + +/** + * @brief Set the seed of the random number generator. + * @param seed: The seed of the random number generator. + * @return none + */ +void sgl_srand(unsigned int seed); + + +#ifdef __cplusplus +} +#endif + +#endif // !__SGL_MATH_H__ diff --git a/User/system/sgl/include/sgl_misc.h b/User/system/sgl/include/sgl_misc.h new file mode 100644 index 0000000..5447606 --- /dev/null +++ b/User/system/sgl/include/sgl_misc.h @@ -0,0 +1,53 @@ +/* source/include/sgl_misc.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_MISC_H__ +#define __SGL_MISC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#if (CONFIG_SGL_BOOT_LOGO) + +/** + * @brief to show the sgl logo after sgl init + * @param none + * @return none + * @note: you can call this function in your main function to show the sgl logo + */ +void sgl_boot_logo(void); + +#endif // ! CONFIG_SGL_BOOT_LOGO + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif // ! __SGL_MISC_H__ diff --git a/User/system/sgl/include/sgl_mm.h b/User/system/sgl/include/sgl_mm.h new file mode 100644 index 0000000..c7fb148 --- /dev/null +++ b/User/system/sgl/include/sgl_mm.h @@ -0,0 +1,112 @@ +/* source/include/sgl_mm.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_MM_H__ +#define __SGL_MM_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief memory monitor info + * @total_size: total size of memory + * @free_size: free size of memory + * @used_size: used size of memory + * @used_rate: used rate of memory: + * | 8 bit | 8 bit | + * | int | dec | + */ +typedef struct sgl_mm_monitor { + size_t total_size; + size_t free_size; + size_t used_size; + size_t used_rate; + +} sgl_mm_monitor_t; + + +/** + * @brief initialize memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_init(void *mem_start, size_t len); + + +/** + * @brief add memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_add_pool(void *mem_start, size_t len); + + +/** + * @brief memory alloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * + * @param size request size of memory + * + * @return point to request memory address +*/ +void* sgl_malloc(size_t size); + + +/** + * @brief memory realloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * @param p the pointer of request size of memory + * @param size request size of memory + */ +void* sgl_realloc(void *p, size_t size); + + +/** + * @brief memory free + * + * @param p the pointer of request size of memory + * + * @return none +*/ +void sgl_free(void *p); + + +/** + * @brief get memory monitor info + * + * @param none + * @return memory monitor info + */ +sgl_mm_monitor_t sgl_mm_get_monitor(void); + + +#ifdef __cplusplus +} +#endif + +#endif // !__SGL_MM_H__ diff --git a/User/system/sgl/include/sgl_theme.h b/User/system/sgl/include/sgl_theme.h new file mode 100644 index 0000000..79e40c1 --- /dev/null +++ b/User/system/sgl/include/sgl_theme.h @@ -0,0 +1,79 @@ +/* source/include/sgl_theme.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_THEME_H__ +#define __SGL_THEME_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#if (CONFIG_SGL_THEME_DEFAULT) +#define SGL_THEME_DESKTOP sgl_rgb(255, 255, 255) +#define SGL_THEME_COLOR sgl_rgb(255, 255, 255) +#define SGL_THEME_BG_COLOR sgl_rgb(0, 0, 0) +#define SGL_THEME_BORDER_WIDTH 2 +#define SGL_THEME_BORDER_COLOR sgl_rgb(0, 0, 0) +#define SGL_THEME_ALPHA 255 +#define SGL_THEME_TEXT_COLOR sgl_rgb(0, 0, 0) +#define SGL_THEME_RADIUS 0 +#define SGL_THEME_SCROLL_RADIUS 3 +#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100) +#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200) + + +#elif (CONFIG_SGL_THEME_DARK) +#define SGL_THEME_DESKTOP sgl_rgb(10, 10, 10) +#define SGL_THEME_COLOR sgl_rgb(50, 50, 50) +#define SGL_THEME_BG_COLOR sgl_rgb(20, 20, 20) +#define SGL_THEME_BORDER_WIDTH 2 +#define SGL_THEME_BORDER_COLOR sgl_rgb(200, 200, 200) +#define SGL_THEME_ALPHA 255 +#define SGL_THEME_TEXT_COLOR sgl_rgb(200, 200, 200) +#define SGL_THEME_RADIUS 0 +#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100) +#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200) + + +#elif (CONFIG_SGL_THEME_LIGHT) +#define SGL_THEME_COLOR sgl_rgb(189, 212, 243) +#define SGL_THEME_BG_COLOR sgl_rgb(255, 255, 255) +#define SGL_THEME_BORDER_WIDTH 2 +#define SGL_THEME_BORDER_COLOR sgl_rgb(0, 0, 0) +#define SGL_THEME_ALPHA 255 +#define SGL_THEME_TEXT_COLOR sgl_rgb(0, 0, 0) +#define SGL_THEME_RADIUS 0 +#define SGL_THEME_SCROLL_BG_COLOR sgl_rgb(100, 100, 100) +#define SGL_THEME_SCROLL_FG_COLOR sgl_rgb(200, 200, 200) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/User/system/sgl/include/sgl_types.h b/User/system/sgl/include/sgl_types.h new file mode 100644 index 0000000..9e5303e --- /dev/null +++ b/User/system/sgl/include/sgl_types.h @@ -0,0 +1,337 @@ +/* source/include/sgl_types.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_TYPES_H__ +#define __SGL_TYPES_H__ + + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Get the offset of internal members of the structure + * + * @struct_t: structure typedef + * @member: member in structure + * + * @return offset of member in the structure +*/ +#define sgl_offsetof(struct_t, member) ((size_t)&((struct_t*)0)->member) + + +/** + * @brief Get the address of the structure instance. + * + * @ptr: address of the structure member. + * @type: type of the structure. + * @member: member name of the ptr in structure. + * @return pointer to address of structure + */ +#define sgl_container_of(ptr, type, member) ((type *)((char *)ptr - sgl_offsetof(type, member))) + + +#ifndef SGL_ARRAY_SIZE +#define SGL_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +#endif + + +#define SGL_ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) +#define SGL_ROUND_UP(x, round) ((((x) + ((round) - 1)) / (round)) * (round)) + +#define SGL_UNUSED(x) (void)(x) + + +#define SGL_POS_INVALID (0xefff) +#define SGL_POS_MAX (8192) +#define SGL_POS_MIN (-8192) +#define SGL_RADIUS_INVALID (0xFFF) + +#define SGL_AREA_MAX {.x1 = SGL_POS_MIN, .y1 = SGL_POS_MIN, .x2 = SGL_POS_MAX, .y2 = SGL_POS_MAX} +#define SGL_AREA_INVALID {.x1 = SGL_POS_MAX, .y1 = SGL_POS_MAX, .x2 = SGL_POS_MIN, .y2 = SGL_POS_MIN} + +#define SGL_WIDTH_INVALID (-1) +#define SGL_WIDTH_MAX (8192) +#define SGL_WIDTH_MIN (0) +#define SGL_HEIGHT_INVALID (-1) +#define SGL_HEIGHT_MAX (8192) +#define SGL_HEIGHT_MIN (0) + + +#define SGL_DIRECT_HORIZONTAL (0) +#define SGL_DIRECT_VERTICAL (1) + + +#define SGL_ALPHA_MAX (255) +#define SGL_ALPHA_MIN (0) +#define SGL_ALPHA_NUM (256) + + +#define SGL_STYLE_OK (0) +#define SGL_STYLE_FAILED (UINT32_MAX) +#define SGL_STYLE_INVALID (UINT32_MAX) + + +#define SGL_COLOR_RGB332 (8) +#define SGL_COLOR_RGB565 (16) +#define SGL_COLOR_RGB888 (24) +#define SGL_COLOR_ARGB8888 (32) + +/* the pixmap format */ +#define SGL_PIXMAP_FMT_NONE (0) +#define SGL_PIXMAP_FMT_RGB332 (1) +#define SGL_PIXMAP_FMT_ARGB2222 (2) +#define SGL_PIXMAP_FMT_RGB565 (3) +#define SGL_PIXMAP_FMT_ARGB4444 (4) +#define SGL_PIXMAP_FMT_RGB888 (5) +#define SGL_PIXMAP_FMT_ARGB8888 (6) +#define SGL_PIXMAP_FMT_RLE_RGB332 (7) +#define SGL_PIXMAP_FMT_RLE_ARGB2222 (8) +#define SGL_PIXMAP_FMT_RLE_RGB565 (9) +#define SGL_PIXMAP_FMT_RLE_ARGB4444 (10) +#define SGL_PIXMAP_FMT_RLE_RGB888 (11) +#define SGL_PIXMAP_FMT_RLE_ARGB8888 (12) +#define SGL_PIXMAP_FMT_MAX (13) + + +#ifdef __GNUC__ /* gcc compiler */ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#define sgl_weak_fn __attribute__((weak)) +#define sgl_section(sec) __attribute__((section(#sec))) +#elif defined(__clang__) /* clang compiler */ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#define sgl_weak_fn __attribute__((weak)) +#define sgl_section(sec) __attribute__((section(#sec))) +#elif defined(__CC_ARM) /* RealView compiler (Keil ARMCC) */ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#define sgl_weak_fn __weak +#define sgl_section(sec) __attribute__((section(#sec))) +#elif defined(__ICCARM__) /* IAR compiler */ +#ifndef likely +# define likely(x) __iar_builtin_expect(!!(x), 1) +# define unlikely(x) __iar_builtin_expect(!!(x), 0) +#endif +#define sgl_weak_fn __weak +#define sgl_section(sec) __section(#sec) +#elif defined(_MSC_VER) /* MSVC compiler */ +#ifndef likely +# define likely(x) (x) +# define unlikely(x) (x) +#endif +#define sgl_weak_fn __declspec(selectany) +#elif defined(__MINGW32__) /* MinGW compiler */ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#define sgl_weak_fn __attribute__((weak)) +#define sgl_section(sec) __attribute__((section(#sec))) +#else /* others compiler */ +#ifndef likely +# define likely(x) (x) +# define unlikely(x) (x) +#endif +#warning "Weak linkage not supported for this compiler" +#endif + + +#define sgl_check_ptr_break(ptr) if (unlikely((ptr) == NULL)) { SGL_LOG_ERROR("Function: %s, Line: %d, "#ptr" is NULL", __func__, __LINE__); return;} +#define sgl_check_ptr_return(ptr, r) if (unlikely((ptr) == NULL)) { SGL_LOG_ERROR("Function: %s, Line: %d, "#ptr" is NULL", __func__, __LINE__); return (r);} + + +/** + * @brief Run once function + * @note you must sure the statement is thread safe + */ +#define SGL_RUN_ONCE(statement) do { \ + static bool _run_once_flag = false; \ + if (unlikely(_run_once_flag == false)){ \ + statement; \ + _run_once_flag = true; \ + } \ + } while(0) + +// prototype: sgl_rgb(uint8_t r, uint8_t g, uint8_t b) +#if (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_ARGB8888 || CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB888) +#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b), \ + .ch.green = (g), \ + .ch.red = (r),} + +#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) << 6), \ + .ch.green = ((((rgb222) >> 2) & 0x03) << 6), \ + .ch.red = ((((rgb222) >> 4) & 0x03) << 6),} + +#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = ((((rgb332) >> 0) & 0x03) << 6), \ + .ch.green = ((((rgb332) >> 2) & 0x07) << 5), \ + .ch.red = ((((rgb332) >> 5) & 0x07) << 5),} + +#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) << 4), \ + .ch.green = ((((rgb444) >> 4) & 0xF) << 4), \ + .ch.red = ((((rgb444) >> 8) & 0xF) << 4),} + +#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((((rgb565) >> 0) & 0x1F) << 3), \ + .ch.green = ((((rgb565) >> 5) & 0x3F) << 2), \ + .ch.red = ((((rgb565) >> 11) & 0x1F) << 3),} + +#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = ((rgb888) >> 0), \ + .ch.green = ((rgb888) >> 8), \ + .ch.red = ((rgb888) >> 16),} + +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB565) +#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b) >> 3, \ + .ch.green = (g) >> 2, \ + .ch.red = (r) >> 3,} + +#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) << 3), \ + .ch.green = ((((rgb222) >> 2) & 0x03) << 4), \ + .ch.red = ((((rgb222) >> 4) & 0x03) << 3),} + +#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = ((((rgb332) >> 0) & 0x03) << 3), \ + .ch.green = ((((rgb332) >> 2) & 0x03) << 2), \ + .ch.red = ((((rgb332) >> 5) & 0x03) << 2),} + +#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) << 1), \ + .ch.green = ((((rgb444) >> 4) & 0xF) << 2), \ + .ch.red = ((((rgb444) >> 8) & 0xF) << 1),} + +#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((rgb565) >> 0) & 0x1F, \ + .ch.green = ((rgb565) >> 5) & 0x3F, \ + .ch.red = ((rgb565) >> 11) & 0x1F,} + +#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = (((rgb888) >> 0) >> 3), \ + .ch.green = (((rgb888) >> 8) >> 2), \ + .ch.red = (((rgb888) >> 16) >> 3),} + +#elif (CONFIG_SGL_FBDEV_PIXEL_DEPTH == SGL_COLOR_RGB332) +#define sgl_rgb(r,g,b) (sgl_color_t){ .ch.blue = (b >> 6), \ + .ch.green = (g >> 5), \ + .ch.red = (r >> 5),} + +#define sgl_rgb222_to_color(rgb222) (sgl_color_t){ .ch.blue = ((((rgb222) >> 0) & 0x03) >> 0), \ + .ch.green = ((((rgb222) >> 2) & 0x03) >> 1), \ + .ch.red = ((((rgb222) >> 4) & 0x03) >> 1),} + +#define sgl_rgb332_to_color(rgb332) (sgl_color_t){ .ch.blue = (((rgb332) >> 0) & 0x03), \ + .ch.green = (((rgb332) >> 3) & 0x07), \ + .ch.red = (((rgb332) >> 5) & 0x07),} + +#define sgl_rgb444_to_color(rgb444) (sgl_color_t){ .ch.blue = ((((rgb444) >> 0) & 0xF) >> 2), \ + .ch.green = ((((rgb444) >> 4) & 0xF) >> 1), \ + .ch.red = ((((rgb444) >> 8) & 0xF) >> 1),} + +#define sgl_rgb565_to_color(rgb565) (sgl_color_t){ .ch.blue = ((((rgb565) >> 0) & 0x1F) >> 3), \ + .ch.green = ((((rgb565) >> 5) & 0x3F) >> 3), \ + .ch.red = ((((rgb565) >> 11) & 0x1F) >> 2),} + +#define sgl_rgb888_to_color(rgb888) (sgl_color_t){ .ch.blue = (((rgb888) >> 0)>> 6), \ + .ch.green = (((rgb888) >> 8) >> 5), \ + .ch.red = (((rgb888) >> 16) >> 6),} + +#endif + + +/** + * Define some basic colors +*/ +#define SGL_COLOR_RED sgl_rgb(0xFF, 0, 0) +#define SGL_COLOR_GREEN sgl_rgb(0, 0xFF, 0) +#define SGL_COLOR_BLUE sgl_rgb(0, 0, 0xFF) +#define SGL_COLOR_WHITE sgl_rgb(0xFF, 0xFF, 0xFF) +#define SGL_COLOR_BLACK sgl_rgb(0, 0, 0) +#define SGL_COLOR_CYAN sgl_rgb(0, 0xFF, 0xFF) +#define SGL_COLOR_MAGENTA sgl_rgb(0xFF, 0, 0xFF) +#define SGL_COLOR_YELLOW sgl_rgb(0xFF, 0xFF, 0) +#define SGL_COLOR_GRAY sgl_rgb(0x80, 0x80, 0x80) +#define SGL_COLOR_DARK_GRAY sgl_rgb(0x40, 0x40, 0x40) +#define SGL_COLOR_LIGHT_GRAY sgl_rgb(0xC0, 0xC0, 0xC0) +#define SGL_COLOR_BRIGHT_PURPLE sgl_rgb(0xFF, 0x00, 0xFF) +#define SGL_COLOR_BRIGHT_BLUE sgl_rgb(0x00, 0xFF, 0xFF) +#define SGL_COLOR_ORANGE sgl_rgb(0xFF, 0xA5, 0x00) +#define SGL_COLOR_DARK_ORANGE sgl_rgb(0xFF, 0x8C, 0x00) +#define SGL_COLOR_RED_ORANGE sgl_rgb(0xFF, 0x45, 0x00) +#define SGL_COLOR_GOLD sgl_rgb(0xFF, 0xD7, 0x00) +#define SGL_COLOR_GOLDENROD sgl_rgb(0xDA, 0xA5, 0x20) +#define SGL_COLOR_BROWN sgl_rgb(0xA5, 0x2A, 0x2A) +#define SGL_COLOR_SADDLE_BROWN sgl_rgb(0x8B, 0x45, 0x13) +#define SGL_COLOR_TOMATO sgl_rgb(0xFF, 0x63, 0x47) +#define SGL_COLOR_CORAL sgl_rgb(0xFF, 0x7F, 0x50) +#define SGL_COLOR_SALMON sgl_rgb(0xFA, 0x80, 0x72) +#define SGL_COLOR_LIME sgl_rgb(0x32, 0xCD, 0x32) +#define SGL_COLOR_OLIVE sgl_rgb(0x80, 0x80, 0x00) +#define SGL_COLOR_DARK_OLIVE_GREEN sgl_rgb(0x55, 0x6B, 0x2F) +#define SGL_COLOR_FOREST_GREEN sgl_rgb(0x22, 0x8B, 0x2F) +#define SGL_COLOR_DARK_GREEN sgl_rgb(0x00, 0x64, 0x00) +#define SGL_COLOR_LAWN_GREEN sgl_rgb(0x7C, 0xFC, 0x00) +#define SGL_COLOR_CHARTREUSE sgl_rgb(0x7F, 0xFF, 0x00) +#define SGL_COLOR_YELLOW_GREEN sgl_rgb(0x9A, 0xCD, 0x32) +#define SGL_COLOR_SPRING_GREEN sgl_rgb(0x00, 0xFF, 0x7F) +#define SGL_COLOR_DEEP_SKY_BLUE sgl_rgb(0x00, 0xBF, 0xFF) +#define SGL_COLOR_DODGER_BLUE sgl_rgb(0x1E, 0x90, 0xFF) +#define SGL_COLOR_ROYAL_BLUE sgl_rgb(0x41, 0x69, 0xE1) +#define SGL_COLOR_MIDNIGHT_BLUE sgl_rgb(0x19, 0x19, 0x70) +#define SGL_COLOR_NAVY sgl_rgb(0x00, 0x00, 0x80) +#define SGL_COLOR_TEAL sgl_rgb(0x00, 0x80, 0x80) +#define SGL_COLOR_DARK_CYAN sgl_rgb(0x00, 0x8B, 0x8B) +#define SGL_COLOR_LIGHT_SEA_GREEN sgl_rgb(0x20, 0xB2, 0xAA) +#define SGL_COLOR_CADET_BLUE sgl_rgb(0x5F, 0x9E, 0xA0) +#define SGL_COLOR_INDIGO sgl_rgb(0x4B, 0x00, 0x82) +#define SGL_COLOR_VIOLET sgl_rgb(0xEE, 0x82, 0xEE) +#define SGL_COLOR_DARK_VIOLET sgl_rgb(0x94, 0x00, 0xD3) +#define SGL_COLOR_MEDIUM_VIOLET_RED sgl_rgb(0xC7, 0x15, 0x85) +#define SGL_COLOR_PINK sgl_rgb(0xFF, 0xC0, 0xCB) +#define SGL_COLOR_HOT_PINK sgl_rgb(0xFF, 0x69, 0xB4) +#define SGL_COLOR_DEEP_PINK sgl_rgb(0xFF, 0x14, 0x93) +#define SGL_COLOR_PLUM sgl_rgb(0xDD, 0xA0, 0xDD) +#define SGL_COLOR_ORCHID sgl_rgb(0xDA, 0x70, 0xD6) +#define SGL_COLOR_TAN sgl_rgb(0xD2, 0xB4, 0x8C) +#define SGL_COLOR_WHEAT sgl_rgb(0xF5, 0xDE, 0xB3) +#define SGL_COLOR_SAND sgl_rgb(0xC2, 0xB2, 0x90) +#define SGL_COLOR_BEIGE sgl_rgb(0xF5, 0xF5, 0xDC) +#define SGL_COLOR_IVORY sgl_rgb(0xFF, 0xFF, 0xF0) +#define SGL_COLOR_LAVENDER sgl_rgb(0xE6, 0xE6, 0xFA) +#define SGL_COLOR_MISTY_ROSE sgl_rgb(0xFF, 0xE4, 0xE1) +#define SGL_COLOR_SEASHELL sgl_rgb(0xFF, 0xF5, 0xEE) +#define SGL_COLOR_FLORAL_WHITE sgl_rgb(0xFF, 0xFA, 0xF0) + + +#ifdef __cplusplus +} +#endif + +#endif //__SGL_TYPES_H__ diff --git a/User/system/sgl/lm.cfg b/User/system/sgl/lm.cfg new file mode 100644 index 0000000..705cefe --- /dev/null +++ b/User/system/sgl/lm.cfg @@ -0,0 +1,117 @@ +# source/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +CONFIG_SGL_FBDEV_PIXEL_DEPTH + choices = 8, 16, 24, 32 + default = 32 + +CONFIG_SGL_FBDEV_ROTATION + choices = 0, 90, 180, 270 + default = 0 + +CONFIG_SGL_FBDEV_RUNTIME_ROTATION + choices = n, y + default = n + +CONFIG_SGL_USE_FBDEV_VRAM + choices = n, y + default = n + +CONFIG_SGL_SYSTICK_MS + choices = [10, 1000] + default = 10 + +# this value must be power of 2, such as 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536 +CONFIG_SGL_EVENT_QUEUE_SIZE + choices = [16, 65536] + default = 32 + +CONFIG_SGL_EVENT_CLICK_INTERVAL + choices = [5, 100] + default = 10 + +CONFIG_SGL_DIRTY_AREA_NUM_MAX + choices = [8, 255] + default = 16 + +CONFIG_SGL_COLOR16_SWAP + choices = n, y + default = n + +CONFIG_SGL_PIXMAP_BILINEAR_INTERP + choices = n, y + default = n + +CONFIG_SGL_ANIMATION + choices = n, y + default = n + +CONFIG_SGL_DEBUG + choices = n, y + default = n + +CONFIG_SGL_LOG_COLOR + choices = n, y + default = n + depends = CONFIG_SGL_DEBUG + +CONFIG_SGL_LOG_LEVEL + choices = 0, 1, 2, 3, 4, 5, 6 + default = 0 + depends = CONFIG_SGL_DEBUG + +CONFIG_SGL_OBJ_USE_NAME + choices = n, y + default = n + +CONFIG_SGL_FONT_COMPRESSED + choices = n, y + default = n + +CONFIG_SGL_FONT_SMALL_TABLE + choices = n, y + default = n + +CONFIG_SGL_LABEL_ROTATION + choices = n, y + default = n + +CONFIG_SGL_BOOT_LOGO + choices = n, y + default = y + +CONFIG_SGL_THEME_DARK + choices = n, y + default = n + + +PATH += ./ include +CFLAG-$(CONFIG_SGL_DEBUG) += -g + + +include "core/lm.cfg" +include "mm/lm.cfg" +include "draw/lm.cfg" +include "widgets/lm.cfg" +include "fonts/lm.cfg" diff --git a/User/system/sgl/mm/build.cmake b/User/system/sgl/mm/build.cmake new file mode 100644 index 0000000..46d5aa5 --- /dev/null +++ b/User/system/sgl/mm/build.cmake @@ -0,0 +1,52 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +if(${SGL_HEAP_ALGO} STREQUAL "tlsf") + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/tlsf/tlsf.c + ${CMAKE_CURRENT_LIST_DIR}/tlsf/sgl_mm.c + ) +endif() + +if(${SGL_HEAP_ALGO} STREQUAL "lwmem") + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/lwmem/lwmem.c + ${CMAKE_CURRENT_LIST_DIR}/lwmem/sgl_mm.c + ) +endif() + +if(${SGL_HEAP_ALGO} STREQUAL "bump") + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/bump/sgl_mm.c + ) +endif() + +if(${SGL_HEAP_ALGO} STREQUAL "other") + set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/other/sgl_mm.c + ) +endif() diff --git a/User/system/sgl/mm/bump/sgl_mm.c b/User/system/sgl/mm/bump/sgl_mm.c new file mode 100644 index 0000000..a0eeb67 --- /dev/null +++ b/User/system/sgl/mm/bump/sgl_mm.c @@ -0,0 +1,137 @@ +/* source/mm/bump/sgl_mm.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * WARNING: This memory allocator is not support free operation, if you free the memory, the memory will be corrupted. + */ + +#include +#include +#include +#include +#include +#include + + +static sgl_mm_monitor_t mem = { + .total_size = 0, + .free_size = 0, + .used_size = 0, +}; + +static void *bump_mem_start = NULL; +static size_t bump_mem_offset = 0; + +/** + * @brief initialize memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_init(void *mem_start, size_t len) +{ + bump_mem_start = mem_start; + mem.total_size += len; + mem.free_size = mem.total_size; +} + + +/** + * @brief add memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_add_pool(void *mem_start, size_t len) +{ + SGL_UNUSED(mem_start); + SGL_UNUSED(len); + SGL_LOG_ERROR("sgl_mm_add_pool is not supported"); + SGL_ASSERT(0); +} + + +/** + * @brief memory alloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * + * @param size request size of memory + * + * @return point to request memory address +*/ +void* sgl_malloc(size_t size) +{ + uint8_t *ptr = (uint8_t*)bump_mem_start; + + if (size == 0 || (bump_mem_offset + size) > mem.total_size) { + return NULL; + } + + ptr += bump_mem_offset; + bump_mem_offset += size; + mem.used_size += size; + mem.free_size -= size; + + return (void*)ptr; +} + + +/** + * @brief memory realloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * @param p the pointer of request size of memory + * @param size request size of memory + */ +void* sgl_realloc(void *p, size_t size) +{ + SGL_UNUSED(p); + SGL_UNUSED(size); + SGL_LOG_ERROR("sgl_realloc is not supported"); + SGL_ASSERT(0); + return NULL; +} + + +/** + * @brief memory free + * + * @param p the pointer of request size of memory + * + * @return none +*/ +void sgl_free(void *p) +{ + SGL_UNUSED(p); + SGL_LOG_ERROR("sgl_free is not supported"); + SGL_ASSERT(0); +} + + +sgl_mm_monitor_t sgl_mm_get_monitor(void) +{ + int integer = (mem.used_size * 100) / mem.total_size; + int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100); + mem.used_rate = integer << 8 | decimal; + mem.free_size = mem.total_size - mem.used_size; + + return mem; +} diff --git a/User/system/sgl/mm/lm.cfg b/User/system/sgl/mm/lm.cfg new file mode 100644 index 0000000..1632170 --- /dev/null +++ b/User/system/sgl/mm/lm.cfg @@ -0,0 +1,66 @@ +# source/mm/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +# Memory management +# Description: +# - tlsf +# A dynamic, fragmentation-resistant allocator designed for real-time and embedded systems +# (e.g., RTOS, MCUs with moderate RAM). It balances speed, memory utilization, and low fragmentation. +# +# - lwmem +# A lightweight, MCU-optimized allocator (developed for embedded systems) that prioritizes minimal +# resource usage (RAM/ROM) while supporting basic dynamic allocation/deallocation. +# +# - bump +# The simplest and fastest memory allocator, often called a "linear allocator" or "stack allocator" +# (though not to be confused with the program stack). It manages a single contiguous block of +# memory (a memory pool) with a single pointer (offset) that "bumps forward" to allocate memory. +# +# - other +# Other memory allocation algorithms, you can implement your own memory allocation algorithm. + +# If you want to use dynamic memory allocation algorithm, you can consider it as an option +CONFIG_SGL_HEAP_ALGO + choices = tlsf, lwmem, bump, other + default = lwmem + + +CONFIG_SGL_FL_INDEX_MAX + choices = [10, 31] + depends = CONFIG_SGL_HEAP_ALGO + default = 20 + + +# Memory size is Byte +CONFIG_SGL_HEAP_MEMORY_SIZE + choices = [1, 10000000] + depends = CONFIG_SGL_HEAP_ALGO + default = 10240 + + + +SRC-$(CONFIG_SGL_HEAP_ALGO == tlsf) += tlsf/tlsf.c tlsf/sgl_mm.c +SRC-$(CONFIG_SGL_HEAP_ALGO == lwmem) += lwmem/lwmem.c lwmem/sgl_mm.c +SRC-$(CONFIG_SGL_HEAP_ALGO == bump) += bump/sgl_mm.c +SRC-$(CONFIG_SGL_HEAP_ALGO == other) += other/sgl_mm.c diff --git a/User/system/sgl/mm/lwmem/lwmem.c b/User/system/sgl/mm/lwmem/lwmem.c new file mode 100644 index 0000000..6773933 --- /dev/null +++ b/User/system/sgl/mm/lwmem/lwmem.c @@ -0,0 +1,1439 @@ +/** + * \file lwmem.c + * \brief Lightweight dynamic memory manager + */ + +/* + * Copyright (c) 2024 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.2.1 + */ +#include "lwmem.h" +#include +#include +#include + +#if LWMEM_CFG_OS +#include "system/lwmem_sys.h" +#endif /* LWMEM_CFG_OS */ + +#if LWMEM_CFG_OS +#define LWMEM_PROTECT(lwobj) lwmem_sys_mutex_wait(&((lwobj)->mutex)) +#define LWMEM_UNPROTECT(lwobj) lwmem_sys_mutex_release(&((lwobj)->mutex)) +#else /* LWMEM_CFG_OS */ +#define LWMEM_PROTECT(lwobj) +#define LWMEM_UNPROTECT(lwobj) +#endif /* !LWMEM_CFG_OS */ + +/* Statistics part */ +#if LWMEM_CFG_ENABLE_STATS +#define LWMEM_INC_STATS(field) (++(field)) +#define LWMEM_UPDATE_MIN_FREE(lwobj) \ + do { \ + if ((lwobj)->mem_available_bytes < (lwobj)->stats.minimum_ever_mem_available_bytes) { \ + (lwobj)->stats.minimum_ever_mem_available_bytes = (lwobj)->mem_available_bytes; \ + } \ + } while (0) +#else +#define LWMEM_INC_STATS(field) +#define LWMEM_UPDATE_MIN_FREE(lwobj) +#endif /* LWMEM_CFG_ENABLE_STATS */ + +/* Verify alignment */ +#if (LWMEM_CFG_ALIGN_NUM & (LWMEM_CFG_ALIGN_NUM - 1) > 0) +#error "LWMEM_ALIGN_BITS must be power of 2" +#endif + +/** + * \brief LwMEM default structure used by application + */ +static lwmem_t lwmem_default; + +/** + * \brief Get LwMEM instance based on user input + * \param[in] in_lwobj: LwMEM instance. Set to `NULL` for default instance + */ +#define LWMEM_GET_LWOBJ(in_lwobj) ((in_lwobj) != NULL ? (in_lwobj) : (&lwmem_default)) + +/** + * \brief Transform alignment number (power of `2`) to bits + */ +#define LWMEM_ALIGN_BITS ((size_t)(((size_t)LWMEM_CFG_ALIGN_NUM) - 1)) + +/** + * \brief Aligns input value to next alignment bits + * + * As an example, when \ref LWMEM_CFG_ALIGN_NUM is set to `4`: + * + * - Input: `0`; Output: `0` + * - Input: `1`; Output: `4` + * - Input: `2`; Output: `4` + * - Input: `3`; Output: `4` + * - Input: `4`; Output: `4` + * - Input: `5`; Output: `8` + * - Input: `6`; Output: `8` + * - Input: `7`; Output: `8` + * - Input: `8`; Output: `8` + */ +#define LWMEM_ALIGN(x) (((x) + (LWMEM_ALIGN_BITS)) & ~(LWMEM_ALIGN_BITS)) + +/** + * \brief Cast input pointer to byte + * \param[in] p: Input pointer to cast to byte pointer + */ +#define LWMEM_TO_BYTE_PTR(p) ((uint8_t*)(p)) + +#if LWMEM_CFG_FULL + +/** + * \brief Size of metadata header for block information + */ +#define LWMEM_BLOCK_META_SIZE LWMEM_ALIGN(sizeof(lwmem_block_t)) + +/** + * \brief Bit indicating memory block is allocated + */ +#define LWMEM_ALLOC_BIT ((size_t)((size_t)1 << (sizeof(size_t) * CHAR_BIT - 1))) + +/** + * \brief Mark written in `next` field when block is allocated + */ +#define LWMEM_BLOCK_ALLOC_MARK (0xDEADBEEF) + +/** + * \brief Check if input block is properly allocated and valid + * \param[in] block: Block to check if properly set as allocated + */ +#define LWMEM_BLOCK_IS_ALLOC(block) \ + ((block) != NULL && ((block)->size & LWMEM_ALLOC_BIT) \ + && (block)->next == (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK)) + +/** + * \brief Get block handle from application pointer + * \param[in] ptr: Input pointer to get block from + */ +#define LWMEM_GET_BLOCK_FROM_PTR(ptr) (void*)((ptr) != NULL ? ((LWMEM_TO_BYTE_PTR(ptr)) - LWMEM_BLOCK_META_SIZE) : NULL) + +/** + * \brief Get block handle from application pointer + * \param[in] block: Input pointer to get block from + */ +#define LWMEM_GET_PTR_FROM_BLOCK(block) \ + (void*)((block) != NULL ? ((LWMEM_TO_BYTE_PTR(block)) + LWMEM_BLOCK_META_SIZE) : NULL) + +/** + * \brief Minimum amount of memory required to make new empty block + * + * Default size is size of meta block + */ +#define LWMEM_BLOCK_MIN_SIZE (LWMEM_BLOCK_META_SIZE) + +/** + * \brief Gets block before input block (marked as prev) and its previous free block + * \param[in] in_lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] in_b: Input block to find previous and its previous + * \param[in] in_pp: Previous previous of input block. Finding will be stored here + * \param[in] in_p: Previous of input block. Finding will be stored here + */ +static void +prv_get_prev_curr_of_block(lwmem_t* in_lwobj, const lwmem_block_t* in_b, lwmem_block_t** in_pp, lwmem_block_t** in_p) { + for (*in_pp = NULL, *in_p = &((in_lwobj)->start_block); *in_p != NULL && (*in_p)->next < in_b; + *in_pp = (*in_p), *in_p = (*in_p)->next) {} +} + +/** + * \brief Set block as allocated + * \param[in] block: Block to set as allocated + */ +static void +prv_block_set_alloc(lwmem_block_t* block) { + if (block != NULL) { + block->size |= LWMEM_ALLOC_BIT; + block->next = (void*)(LWMEM_TO_BYTE_PTR(0) + LWMEM_BLOCK_ALLOC_MARK); + } +} + +/** + * \brief Get region aligned start address and aligned size + * \param[in] region: Region to check for size and address + * \param[out] msa: Memory start address output variable + * \param[out] msz: Memory size output variable + * \return `1` if region valid, `0` otherwise + */ +static uint8_t +prv_get_region_addr_size(const lwmem_region_t* region, uint8_t** msa, size_t* msz) { + size_t mem_size = 0; + uint8_t* mem_start_addr = NULL; + + if (region == NULL || msa == NULL || msz == NULL) { + return 0; + } + *msa = NULL; + *msz = 0; + + /* + * Start address must be aligned to configuration + * Increase start address and decrease effective region size + */ + mem_start_addr = region->start_addr; + mem_size = region->size; + if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { /* Check alignment boundary */ + mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS); + mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(region->start_addr)); + } + + /* Check region size and align it to config bits */ + mem_size &= ~LWMEM_ALIGN_BITS; /* Align the size to lower bits */ + if (mem_size < (2 * LWMEM_BLOCK_MIN_SIZE)) { + return 0; + } + + /* Check final memory size */ + if (mem_size >= (2 * LWMEM_BLOCK_MIN_SIZE)) { + *msa = mem_start_addr; + *msz = mem_size; + + return 1; + } + return 0; +} + +/** + * \brief Insert free block to linked list of free blocks + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] nblk: New free block to insert into linked list + */ +static void +prv_insert_free_block(lwmem_t* const lwobj, lwmem_block_t* nblk) { + lwmem_block_t* prev; + + /* Check valid inputs */ + if (nblk == NULL) { + return; + } + + /* + * Try to find position to put new block in-between + * Search until all free block addresses are lower than entry block + */ + for (prev = &(lwobj->start_block); prev != NULL && prev->next < nblk; prev = prev->next) {} + + /* This is hard error with wrong memory usage */ + if (prev == NULL) { + return; + } + + /* + * At this point we have valid previous block + * Previous block is last free block before input block + */ + +#if LWMEM_CFG_CLEAN_MEMORY + /* + * Reset user memory. This is to reset memory + * after it has been freed by the application. + * + * By doing this, we protect data left by app + * and we make sure new allocations cannot see old information + */ + if (nblk != NULL) { + void* ptr = LWMEM_GET_PTR_FROM_BLOCK(nblk); + if (ptr != NULL) { + LWMEM_MEMSET(ptr, 0x00, nblk->size - LWMEM_BLOCK_META_SIZE); + } + } +#endif /* LWMEM_CFG_RESET_MEMORY */ + + /* + * Check if previous block and input block together create one big contiguous block + * If this is the case, merge blocks together and increase previous block by input block size + */ + if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(nblk)) { + prev->size += nblk->size; /* Increase current block by size of new block */ + nblk = prev; /* New block and current are now the same thing */ + /* + * It is important to set new block as current one + * as this allows merging previous and next blocks together with new block + * at the same time; follow next steps + */ + } + + /* + * Check if new block and next of previous create big contiguous block + * Do not merge with "end of region" indication (commented part of if statement) + */ + if (prev->next != NULL && prev->next->size > 0 /* Do not remove "end of region" indicator in each region */ + && (LWMEM_TO_BYTE_PTR(nblk) + nblk->size) == LWMEM_TO_BYTE_PTR(prev->next)) { + if (prev->next == lwobj->end_block) { /* Does it points to the end? */ + nblk->next = lwobj->end_block; /* Set end block pointer */ + } else { + /* Expand of current block for size of next free block which is right behind new block */ + nblk->size += prev->next->size; + nblk->next = prev->next->next; /* Next free is pointed to the next one of previous next */ + } + } else { + nblk->next = prev->next; /* Set next of input block as next of current one */ + } + + /* + * If new block has not been set as current (and expanded), + * then link them together, otherwise ignore as it would point to itself + */ + if (prev != nblk) { + prev->next = nblk; + } +} + +/** + * \brief Split too big block and add it to list of free blocks + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] block: Pointer to block with size already set + * \param[in] new_block_size: New block size to be set + * \return `1` if block splitted, `0` otherwise + */ +static uint8_t +prv_split_too_big_block(lwmem_t* const lwobj, lwmem_block_t* block, size_t new_block_size) { + lwmem_block_t* next; + size_t block_size, is_alloc_bit; + uint8_t success = 0; + + is_alloc_bit = block->size & LWMEM_ALLOC_BIT; /* Check if allocation bit is set */ + block_size = block->size & ~LWMEM_ALLOC_BIT; /* Use size without allocated bit */ + + /* + * If current block size is greater than requested size, + * it is possible to create empty block at the end of existing one + * and add it back to list of empty blocks + */ + if ((block_size - new_block_size) >= LWMEM_BLOCK_MIN_SIZE) { + next = (void*)(LWMEM_TO_BYTE_PTR(block) + new_block_size); /* Put next block after size of current allocation */ + next->size = block_size - new_block_size; /* Modify block data */ + block->size = new_block_size; /* Current size is now smaller */ + + lwobj->mem_available_bytes += next->size; /* Increase available bytes by new block size */ + prv_insert_free_block(lwobj, next); /* Add new block to the free list */ + + success = 1; + } else { + /* TODO: If next of current is free, check if we can increase next by at least some bytes */ + /* This can only happen during reallocation process when allocated block is reallocated to previous one */ + /* Very rare case, but may happen! */ + } + + /* If allocation bit was set before, set it now again */ + if (is_alloc_bit) { + prv_block_set_alloc(block); + } + return success; +} + +/** + * \brief Private allocation function + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Pointer to region to allocate from. + * Set to `NULL` for any region + * \param[in] size: Application wanted size, excluding size of meta header + * \return Pointer to allocated memory, `NULL` otherwise + */ +static void* +prv_alloc(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) { + lwmem_block_t *prev, *curr; + void* retval = NULL; + + /* Calculate final size including meta data size */ + const size_t final_size = LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; + + /* Check if initialized and if size is in the limits */ + if (lwobj->end_block == NULL || final_size == LWMEM_BLOCK_META_SIZE || (final_size & LWMEM_ALLOC_BIT) > 0) { + return NULL; + } + + /* Set default values */ + prev = &(lwobj->start_block); /* Use pointer from custom lwmem block */ + curr = prev->next; /* Curr represents first actual free block */ + + /* + * If region is not set to NULL, + * request for memory allocation came from specific region: + * + * - Start at the beginning like normal (from very first region) + * - Loop until free block is between region start addr and its size + */ + if (region != NULL) { + uint8_t* region_start_addr; + size_t region_size; + + /* Get data about region */ + if (!prv_get_region_addr_size(region, ®ion_start_addr, ®ion_size)) { + return NULL; + } + + /* + * Scan all regions from lwmem and find first available block + * which is within address of region and is big enough + */ + for (; curr != NULL; prev = curr, curr = curr->next) { + /* Check bounds */ + if (curr->next == NULL || curr == lwobj->end_block) { + return NULL; + } + if ((uint8_t*)curr < (uint8_t*)region_start_addr) { /* Check if we reached region */ + continue; + } + if ((uint8_t*)curr >= (uint8_t*)(region_start_addr + region_size)) { /* Check if we are out already */ + return NULL; + } + if (curr->size >= final_size) { + break; /* Free block identified */ + } + } + } else { + /* + * Try to find first block with at least `size` bytes of available memory + * Loop until size of current block is smaller than requested final size + */ + for (; curr != NULL && curr->size < final_size; prev = curr, curr = curr->next) { + if (curr->next == NULL || curr == lwobj->end_block) { /* If no more blocks available */ + return NULL; /* No sufficient memory available to allocate block of memory */ + } + } + } + + /* Check curr pointer. During normal use, this should be always false */ + if (curr == NULL) { + return NULL; + } + + /* There is a valid block available */ + retval = LWMEM_GET_PTR_FROM_BLOCK(curr); /* Return pointer does not include meta part */ + prev->next = curr->next; /* Remove this block from linked list by setting next of previous to next of current */ + + /* curr block is now removed from linked list */ + + lwobj->mem_available_bytes -= curr->size; /* Decrease available bytes by allocated block size */ + prv_split_too_big_block(lwobj, curr, final_size); /* Split block if it is too big */ + prv_block_set_alloc(curr); /* Set block as allocated */ + + LWMEM_UPDATE_MIN_FREE(lwobj); + LWMEM_INC_STATS(lwobj->stats.nr_alloc); + + return retval; +} + +/** + * \brief Free input pointer + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] ptr: Input pointer to free + */ +static void +prv_free(lwmem_t* const lwobj, void* const ptr) { + lwmem_block_t* const block = LWMEM_GET_BLOCK_FROM_PTR(ptr); + if (LWMEM_BLOCK_IS_ALLOC(block)) { /* Check if block is valid */ + block->size &= ~LWMEM_ALLOC_BIT; /* Clear allocated bit indication */ + + lwobj->mem_available_bytes += block->size; /* Increase available bytes */ + prv_insert_free_block(lwobj, block); /* Put block back to list of free block */ + + LWMEM_INC_STATS(lwobj->stats.nr_free); + } +} + +/** + * \brief Reallocates already allocated memory with new size + * + * Function behaves differently, depends on input parameter of `ptr` and `size`: + * + * - `ptr == NULL; size == 0`: Function returns `NULL`, no memory is allocated or freed + * - `ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(size)` + * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` + * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success + * + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Pointer to region to allocate from. + * Set to `NULL` for any region + * \param[in] ptr: Memory block previously allocated with one of allocation functions. + * It may be set to `NULL` to create new clean allocation + * \param[in] size: Size of new memory to reallocate + * \return Pointer to allocated memory on success, `NULL` otherwise + */ +static void* +prv_realloc(lwmem_t* const lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { + lwmem_block_t *block = NULL, *prevprev = NULL, *prev = NULL; + size_t block_size; /* Holds size of input block (ptr), including metadata size */ + const size_t final_size = + LWMEM_ALIGN(size) + LWMEM_BLOCK_META_SIZE; /* Holds size of new requested block size, including metadata size */ + void* retval; /* Return pointer, used with LWMEM_RETURN macro */ + + /* Check optional input parameters */ + if (size == 0) { + if (ptr != NULL) { + prv_free(lwobj, ptr); + } + return NULL; + } + if (ptr == NULL) { + return prv_alloc(lwobj, region, size); + } + + /* Try to reallocate existing pointer */ + if ((size & LWMEM_ALLOC_BIT) || (final_size & LWMEM_ALLOC_BIT)) { + return NULL; + } + + /* Process existing block */ + block = LWMEM_GET_BLOCK_FROM_PTR(ptr); + if (!LWMEM_BLOCK_IS_ALLOC(block)) { + + /* Hard error. Input pointer is not NULL and block is not considered allocated */ + return NULL; + } + block_size = block->size & ~LWMEM_ALLOC_BIT; /* Get actual block size, without memory allocation bit */ + + /* Check current block size is the same as new requested size */ + if (block_size == final_size) { + return ptr; /* Just return pointer, nothing to do */ + } + + /* + * Abbreviations + * + * - "Current block" or "Input block" is allocated block from input variable "ptr" + * - "Next free block" is next free block, on address space after input block + * - "Prev free block" is last free block, on address space before input block + * - "PrevPrev free block" is previous free block of "Prev free block" + */ + + /* + * When new requested size is smaller than existing one, + * it is enough to modify size of current block only. + * + * If new requested size is much smaller than existing one, + * check if it is possible to create new empty block and add it to list of empty blocks + * + * Application returns same pointer + */ + if (final_size < block_size) { + if ((block_size - final_size) >= LWMEM_BLOCK_MIN_SIZE) { + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + } else { + /* + * It is not possible to create new empty block at the end of input block + * + * But if next free block is just after input block, + * it is possible to find this block and increase it by "block_size - final_size" bytes + */ + + /* Find free blocks before input block */ + prv_get_prev_curr_of_block(lwobj, block, &prevprev, &prev); + + /* Check if current block and next free are connected */ + if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) + && prev->next->size > 0) { /* Must not be end of region indicator */ + /* Make temporary variables as prev->next will point to different location */ + const size_t tmp_size = prev->next->size; + void* const tmp_next = prev->next->next; + + /* Shift block up, effectively increase its size */ + prev->next = (void*)(LWMEM_TO_BYTE_PTR(prev->next) - (block_size - final_size)); + prev->next->size = tmp_size + (block_size - final_size); + prev->next->next = tmp_next; + + /* Increase available bytes by increase of free block */ + lwobj->mem_available_bytes += block_size - final_size; + + block->size = final_size; /* Block size is requested size */ + } + } + prv_block_set_alloc(block); /* Set block as allocated */ + return ptr; /* Return existing pointer */ + } + + /* New requested size is bigger than current block size is */ + + /* Find last free (and its previous) block, located just before input block */ + prv_get_prev_curr_of_block(lwobj, block, &prevprev, &prev); + + /* If entry could not be found, there is a hard error */ + if (prev == NULL) { + return NULL; + } + + /* Order of variables is: | prevprev ---> prev --->--->--->--->--->--->--->--->--->---> prev->next | */ + /* | (input_block, which is not on a list) | */ + /* Input block points to address somewhere between "prev" and "prev->next" pointers */ + + /* Check if "block" and next free "prev->next" create contiguous memory with size of at least new requested size */ + if ((LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) + && (block_size + prev->next->size) >= final_size) { + + /* + * Merge blocks together by increasing current block with size of next free one + * and remove next free from list of free blocks + */ + lwobj->mem_available_bytes -= prev->next->size; /* For now decrease effective available bytes */ + LWMEM_UPDATE_MIN_FREE(lwobj); + block->size = block_size + prev->next->size; /* Increase effective size of new block */ + prev->next = prev->next->next; /* Set next to next's next, + effectively remove expanded block from free list */ + + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + prv_block_set_alloc(block); /* Set block as allocated */ + return ptr; /* Return existing pointer */ + } + + /* + * Check if "block" and last free before "prev" create contiguous memory with size of at least new requested size. + * + * It is necessary to make a memory move and shift content up as new return pointer is now upper on address space + */ + if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) && (prev->size + block_size) >= final_size) { + /* Move memory from block to block previous to current */ + void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); + void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); + + /* + * If memmove overwrites metadata of current block (when shifting content up), + * it is not an issue as we know its size (block_size) and next is already NULL. + * + * Memmove must be used to guarantee move of data as addresses + their sizes may overlap + * + * Metadata of "prev" are not modified during memmove + */ + LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); + + lwobj->mem_available_bytes -= prev->size; /* For now decrease effective available bytes */ + LWMEM_UPDATE_MIN_FREE(lwobj); + prev->size += block_size; /* Increase size of input block size */ + prevprev->next = prev->next; /* Remove prev from free list as it is now being used + for allocation together with existing block */ + block = prev; /* Move block pointer to previous one */ + + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + prv_block_set_alloc(block); /* Set block as allocated */ + return new_data_ptr; /* Return new data ptr */ + } + + /* + * At this point, it was not possible to expand existing block with free before or free after due to: + * - Input block & next free block do not create contiguous block or its new size is too small + * - Previous free block & input block do not create contiguous block or its new size is too small + * + * Last option is to check if previous free block "prev", input block "block" and next free block "prev->next" create contiguous block + * and size of new block (from 3 contiguous blocks) together is big enough + */ + if ((LWMEM_TO_BYTE_PTR(prev) + prev->size) == LWMEM_TO_BYTE_PTR(block) + && (LWMEM_TO_BYTE_PTR(block) + block_size) == LWMEM_TO_BYTE_PTR(prev->next) + && (prev->size + block_size + prev->next->size) >= final_size) { + + /* Move memory from block to block previous to current */ + void* const old_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(block); + void* const new_data_ptr = LWMEM_GET_PTR_FROM_BLOCK(prev); + + /* + * If memmove overwrites metadata of current block (when shifting content up), + * it is not an issue as we know its size (block_size) and next is already NULL. + * + * Memmove must be used to guarantee move of data as addresses and their sizes may overlap + * + * Metadata of "prev" are not modified during memmove + */ + LWMEM_MEMMOVE(new_data_ptr, old_data_ptr, block_size); + + /* Decrease effective available bytes for free blocks before and after input block */ + lwobj->mem_available_bytes -= prev->size + prev->next->size; + LWMEM_UPDATE_MIN_FREE(lwobj); + prev->size += block_size + prev->next->size; /* Increase size of new block by size of 2 free blocks */ + + /* Remove free block before current one and block after current one from linked list (remove 2) */ + prevprev->next = prev->next->next; + block = prev; /* Previous block is now current */ + + prv_split_too_big_block(lwobj, block, final_size); /* Split block if it is too big */ + prv_block_set_alloc(block); /* Set block as allocated */ + return new_data_ptr; /* Return new data ptr */ + } + + /* + * If application reaches this point, it means: + * - New requested size is greater than input block size + * - Input block & next free block do not create contiguous block or its new size is too small + * - Last free block & input block do not create contiguous block or its new size is too small + * - Last free block & input block & next free block do not create contiguous block or its size is too small + * + * Final solution is to find completely new empty block of sufficient size and copy content from old one to new one + */ + retval = prv_alloc(lwobj, region, size); /* Try to allocate new block */ + if (retval != NULL) { + /* Get application size from input pointer, then copy content to new block */ + block_size = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; + LWMEM_MEMCPY(retval, ptr, size > block_size ? block_size : size); + prv_free(lwobj, ptr); /* Free old block */ + } + return retval; +} + +/** + * \brief Assign the memory structure for advanced memory allocation system + * + * \param lwobj + * \param regions + * \return size_t + */ +static size_t +prv_assignmem(lwmem_t* lwobj, const lwmem_region_t* regions) { + uint8_t* mem_start_addr = NULL; + size_t mem_size = 0; + lwmem_block_t *first_block = NULL, *prev_end_block = NULL; + + for (size_t idx = 0; regions->size > 0 && regions->start_addr != NULL; ++idx, ++regions) { + /* Get region start address and size, stop on failure */ + if (!prv_get_region_addr_size(regions, &mem_start_addr, &mem_size)) { + continue; + } + + /* + * If end_block == NULL, this indicates first iteration. + * In first indication application shall set start_block and never again + * end_block value holds + */ + if (lwobj->end_block == NULL) { + /* + * Next entry of start block is first region + * It points to beginning of region data + * In the later step(s) first block is manually set on top of memory region + */ + lwobj->start_block.next = (void*)mem_start_addr; + lwobj->start_block.size = 0; /* Size of dummy start block is zero */ + } + + /* Save current end block status as it is used later for linked list insertion */ + prev_end_block = lwobj->end_block; + + /* Put end block to the end of the region with size = 0 */ + lwobj->end_block = (void*)(mem_start_addr + mem_size - LWMEM_BLOCK_META_SIZE); + lwobj->end_block->next = NULL; /* End block in region does not have next entry */ + lwobj->end_block->size = 0; /* Size of end block is zero */ + + /* + * Create memory region first block. + * + * First block meta size includes size of metadata too + * Subtract MEM_BLOCK_META_SIZE as there is one more block (end_block) at the end of region + * + * Actual maximal available size for application in the region is mem_size - 2 * MEM_BLOCK_META_SIZE + */ + first_block = (void*)mem_start_addr; + first_block->next = lwobj->end_block; /* Next block of first is last block */ + first_block->size = mem_size - LWMEM_BLOCK_META_SIZE; + + /* Check if previous regions exist by checking previous end block state */ + if (prev_end_block != NULL) { + prev_end_block->next = first_block; /* End block of previous region now points to start of current region */ + } + + lwobj->mem_available_bytes += first_block->size; /* Increase number of available bytes */ + ++lwobj->mem_regions_count; /* Increase number of used regions */ + } + +#if defined(LWMEM_DEV) + /* Copy default state of start block */ + LWMEM_MEMCPY(&lwmem_default.start_block_first_use, &lwmem_default.start_block, sizeof(lwmem_default.start_block)); +#endif /* defined(LWMEM_DEV) */ +#if LWMEM_CFG_ENABLE_STATS + lwobj->stats.mem_size_bytes = lwobj->mem_available_bytes; + lwobj->stats.minimum_ever_mem_available_bytes = lwobj->mem_available_bytes; +#endif + + return lwobj->mem_regions_count; /* Return number of regions used by manager */ +} + +#else /* LWMEM_CFG_FULL */ + +/** + * \brief Assign the regions for simple algorithm + * + * At this point, regions check has been performed, so we assume + * everything is ready to proceed + * + * \param lwobj: LwMEM object + * \param regions: List of regions to assign + * \return Number of regions used + */ +static size_t +prv_assignmem_simple(lwmem_t* const lwobj, const lwmem_region_t* regions) { + uint8_t* mem_start_addr = regions[0].start_addr; + size_t mem_size = regions[0].size; + + /* Adjust alignment data */ + if (((size_t)mem_start_addr) & LWMEM_ALIGN_BITS) { + mem_start_addr += ((size_t)LWMEM_CFG_ALIGN_NUM) - ((size_t)mem_start_addr & LWMEM_ALIGN_BITS); + mem_size -= (size_t)(mem_start_addr - LWMEM_TO_BYTE_PTR(regions[0].start_addr)); + } + + /* Align mem to alignment*/ + mem_size = mem_size & ~LWMEM_ALIGN_BITS; + + /* Store the available information */ + lwobj->mem_available_bytes = mem_size; + lwobj->mem_next_available_ptr = mem_start_addr; + lwobj->is_initialized = 1; + return 1; /* One region is being used only for now */ +} + +/** + * \brief Simple allocation algorithm, that can only allocate memory, + * but it does not support free. + * + * It uses simple first-in-first-serve concept, + * where memory grows upward gradually, up until it reaches the end + * of memory area + * + * \param lwobj: LwMEM object + * \param region: Selected region. Not used in the current revision, + * but footprint remains the same if one day library will support it + * \param size: Requested allocation size + * \return `NULL` on failure, or pointer to allocated memory + */ +static void* +prv_alloc_simple(lwmem_t* const lwobj, const lwmem_region_t* region, const size_t size) { + void* retval = NULL; + const size_t alloc_size = LWMEM_ALIGN(size); + + if (alloc_size <= lwobj->mem_available_bytes) { + retval = lwobj->mem_next_available_ptr; + + /* Get ready for next iteration */ + lwobj->mem_next_available_ptr += alloc_size; + lwobj->mem_available_bytes -= alloc_size; + } + (void)region; + return retval; +} + +#endif /* LWMEM_CFG_FULL */ + +/** + * \brief Initializes and assigns user regions for memory used by allocator algorithm + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] regions: Pointer to array of regions with address and respective size. + * Regions must be in increasing order (start address) and must not overlap in-between. + * Last region entry must have address `NULL` and size set to `0` + * \code{.c} +//Example definition +lwmem_region_t regions[] = { + { (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long + { (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long + { (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long + { NULL, 0 } //Array termination indicator +} +\endcode + * \return `0` on failure, number of final regions used for memory manager on success + * \note This function is not thread safe when used with operating system. + * It must be called only once to setup memory regions + */ +size_t +lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions) { + uint8_t* mem_start_addr = NULL; + size_t mem_size = 0, len = 0; + + lwobj = LWMEM_GET_LWOBJ(lwobj); + + /* Check first things first */ + if (regions == NULL +#if LWMEM_CFG_FULL + || lwobj->end_block != NULL /* Init function may only be called once per lwmem instance */ +#else + || lwobj->is_initialized /* Already initialized? */ +#endif /* LWMEM_CFG_FULL */ + ) { + return 0; + } + + /* Check values entered by application */ + mem_start_addr = (void*)0; + mem_size = 0; + for (size_t idx = 0;; ++idx) { + /* + * Check for valid entry or end of array descriptor + * Invalid entry is considered as "end-of-region" indicator + */ + if (regions[idx].size == 0 && regions[idx].start_addr == NULL) { + len = idx; + if (len == 0) { + return 0; + } + break; + } + +#if !LWMEM_CFG_FULL + /* + * In case of simple allocation algorithm, we (for now!) only allow one region. + * Return zero value if user passed more than one region in a sequence. + */ + else if (idx > 0) { + return 0; + } +#endif /* LWMEM_CFG_FULL */ + + /* New region(s) must be higher (in address space) than previous one */ + if ((mem_start_addr + mem_size) > LWMEM_TO_BYTE_PTR(regions[idx].start_addr)) { + return 0; + } + + /* Save new values for next round */ + mem_start_addr = regions[idx].start_addr; + mem_size = regions[idx].size; + } + + /* Final init and check before initializing the regions */ + if (len == 0 +#if LWMEM_CFG_OS + || lwmem_sys_mutex_isvalid(&(lwobj->mutex)) /* Check if mutex valid already = must not be */ + || !lwmem_sys_mutex_create(&(lwobj->mutex)) /* Final step = try to create mutex for new instance */ +#endif /* LWMEM_CFG_OS */ + ) { + return 0; + } + +#if LWMEM_CFG_FULL + return prv_assignmem(lwobj, regions); +#else /* LWMEM_CFG_FULL */ + return prv_assignmem_simple(lwobj, regions); +#endif /* LWMEM_CFG_FULL */ +} + +/** + * \brief Allocate memory of requested size in specific lwmem instance and optional region. + * \note This is an extended malloc version function declaration to support advanced features + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Optional region instance within LwMEM instance to force allocation from. + * Set to `NULL` to use any region within LwMEM instance + * \param[in] size: Number of bytes to allocate + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size) { + void* ptr = NULL; + + lwobj = LWMEM_GET_LWOBJ(lwobj); + + LWMEM_PROTECT(lwobj); +#if LWMEM_CFG_FULL + ptr = prv_alloc(lwobj, region, size); +#else /* LWMEM_CFG_FULL */ + ptr = prv_alloc_simple(lwobj, region, size); +#endif /* LWMEM_CFG_FULL */ + LWMEM_UNPROTECT(lwobj); + return ptr; +} + +/** + * \brief Allocate contiguous block of memory for requested number of items and its size + * in specific lwmem instance and region. + * + * It resets allocated block of memory to zero if allocation is successful + * + * \note This is an extended calloc version function declaration to support advanced features + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Optional region instance within LwMEM instance to force allocation from. + * Set to `NULL` to use any region within LwMEM instance + * \param[in] nitems: Number of elements to be allocated + * \param[in] size: Size of each element, in units of bytes + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size) { + void* ptr = NULL; + const size_t alloc_size = size * nitems; + + lwobj = LWMEM_GET_LWOBJ(lwobj); + + LWMEM_PROTECT(lwobj); +#if LWMEM_CFG_FULL + ptr = prv_alloc(lwobj, region, alloc_size); +#else /* LWMEM_CFG_FULL */ + ptr = prv_alloc_simple(lwobj, region, alloc_size); +#endif /* LWMEM_CFG_FULL */ + LWMEM_UNPROTECT(lwobj); + + if (ptr != NULL) { + LWMEM_MEMSET(ptr, 0x00, alloc_size); + } + return ptr; +} + +#if LWMEM_CFG_FULL || __DOXYGEN__ + +/** + * \brief Reallocates already allocated memory with new size in specific lwmem instance and region. + * + * \note This function may only be used with allocations returned by any of `_from` API functions + * + * Function behaves differently, depends on input parameter of `ptr` and `size`: + * + * - `ptr == NULL; size == 0`: Function returns `NULL`, no memory is allocated or freed + * - `ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(region, size)` + * - `ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)` + * - `ptr != NULL; size > 0`: Function tries to allocate new memory of copy content before returning pointer on success + * + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Pointer to region to allocate from. + * Set to `NULL` to use any region within LwMEM instance. + * Instance must be the same as used during allocation procedure + * \param[in] ptr: Memory block previously allocated with one of allocation functions. + * It may be set to `NULL` to create new clean allocation + * \param[in] size: Size of new memory to reallocate + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size) { + void* p; + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + p = prv_realloc(lwobj, region, ptr, size); + LWMEM_UNPROTECT(lwobj); + return p; +} + +/** + * \brief Safe version of realloc_ex function. + * + * After memory is reallocated, input pointer automatically points to new memory + * to prevent use of dangling pointers. When reallocation is not successful, + * original pointer is not modified and application still has control of it. + * + * It is advised to use this function when reallocating memory. + * + * Function behaves differently, depends on input parameter of `ptr` and `size`: + * + * - `ptr == NULL`: Invalid input, function returns `0` + * - `*ptr == NULL; size == 0`: Function returns `0`, no memory is allocated or freed + * - `*ptr == NULL; size > 0`: Function tries to allocate new block of memory with `size` length, equivalent to `malloc(size)` + * - `*ptr != NULL; size == 0`: Function frees memory, equivalent to `free(ptr)`, sets input pointer pointing to `NULL` + * - `*ptr != NULL; size > 0`: Function tries to reallocate existing pointer with new size and copy content to new block + * + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance + * \param[in] region: Pointer to region to allocate from. + * Set to `NULL` to use any region within LwMEM instance. + * Instance must be the same as used during allocation procedure + * \param[in] ptr: Pointer to pointer to allocated memory. Must not be set to `NULL`. + * If reallocation is successful, it modifies pointer's pointing address, + * or sets it to `NULL` in case of `free` operation + * \param[in] size: New requested size in bytes + * \return `1` if successfully reallocated, `0` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +int +lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size) { + void* new_ptr; + + /* + * Input pointer must not be NULL otherwise, + * in case of successful allocation, we have memory leakage + * aka. allocated memory where noone is pointing to it + */ + if (ptr == NULL) { + return 0; + } + + new_ptr = lwmem_realloc_ex(lwobj, region, *ptr, size); /* Try to reallocate existing pointer */ + if (new_ptr != NULL) { + *ptr = new_ptr; + } else if (size == 0) { /* size == 0 means free input memory */ + *ptr = NULL; + return 1; + } + return new_ptr != NULL; +} + +/** + * \brief Free previously allocated memory using one of allocation functions + * in specific lwmem instance. + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. + * Instance must be the same as used during allocation procedure + * \note This is an extended free version function declaration to support advanced features + * \param[in] ptr: Memory to free. `NULL` pointer is valid input + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void +lwmem_free_ex(lwmem_t* lwobj, void* const ptr) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + prv_free(lwobj, ptr); + LWMEM_UNPROTECT(lwobj); +} + +/** + * \brief Safe version of free function + * + * After memory is freed, input pointer is safely set to `NULL` + * to prevent use of dangling pointers. + * + * It is advised to use this function when freeing memory. + * + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. + * Instance must be the same as used during allocation procedure + * \param[in] ptr: Pointer to pointer to allocated memory. + * When set to non `NULL`, pointer is freed and set to `NULL` + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void +lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr) { + if (ptr != NULL && *ptr != NULL) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + prv_free(lwobj, *ptr); + LWMEM_UNPROTECT(lwobj); + *ptr = NULL; + } +} + +/** + * \brief Get user size of allocated memory + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. + * Instance must be the same as used during allocation procedure + * \param[in] ptr: Pointer to allocated memory + * \return Block size for user in units of bytes + */ +size_t +lwmem_get_size_ex(lwmem_t* lwobj, void* ptr) { + lwmem_block_t* block; + uint32_t len = 0; + + if (ptr != NULL) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + block = LWMEM_GET_BLOCK_FROM_PTR(ptr); + if (LWMEM_BLOCK_IS_ALLOC(block)) { + len = (block->size & ~LWMEM_ALLOC_BIT) - LWMEM_BLOCK_META_SIZE; + } + LWMEM_UNPROTECT(lwobj); + } + return len; +} + +#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ + +#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ + +/** + * \brief Get statistics of a LwMEM instance + * \param[in] lwobj: LwMEM instance. Set to `NULL` to use default instance. + * Instance must be the same as used during allocation procedure + * \param[in,out] stats: Pointer to \ref lwmem_stats_t to store result + */ +void +lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats) { + if (stats != NULL) { + lwobj = LWMEM_GET_LWOBJ(lwobj); + LWMEM_PROTECT(lwobj); + *stats = lwobj->stats; + stats->mem_available_bytes = lwobj->mem_available_bytes; + LWMEM_UNPROTECT(lwobj); + } +} + +/** + * \brief Get statistics of a default LwMEM instance + * \param[in,out] stats: Pointer to \ref lwmem_stats_t to store result + */ +size_t +lwmem_get_size(lwmem_stats_t* stats) { + lwmem_get_stats_ex(NULL, stats); +} + +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ + +/** + * \note This is a wrapper for \ref lwmem_assignmem_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] regions: Pointer to array of regions with address and respective size. + * Regions must be in increasing order (start address) and must not overlap in-between. + * Last region entry must have address `NULL` and size set to `0` + * \code{.c} +//Example definition +lwmem_region_t regions[] = { + { (void *)0x10000000, 0x1000 }, //Region starts at address 0x10000000 and is 0x1000 bytes long + { (void *)0x20000000, 0x2000 }, //Region starts at address 0x20000000 and is 0x2000 bytes long + { (void *)0x30000000, 0x3000 }, //Region starts at address 0x30000000 and is 0x3000 bytes long + { NULL, 0 } //Array termination indicator +} +\endcode + * \return `0` on failure, number of final regions used for memory manager on success + */ +size_t +lwmem_assignmem(const lwmem_region_t* regions) { + return lwmem_assignmem_ex(NULL, regions); +} + +/** + * \note This is a wrapper for \ref lwmem_malloc_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] size: Size to allocate in units of bytes + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_malloc(size_t size) { + return lwmem_malloc_ex(NULL, NULL, size); +} + +/** + * \note This is a wrapper for \ref lwmem_calloc_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] nitems: Number of elements to be allocated + * \param[in] size: Size of each element, in units of bytes + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_calloc(size_t nitems, size_t size) { + return lwmem_calloc_ex(NULL, NULL, nitems, size); +} + +#if LWMEM_CFG_FULL || __DOXYGEN__ + +/** + * \note This is a wrapper for \ref lwmem_realloc_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] ptr: Memory block previously allocated with one of allocation functions. + * It may be set to `NULL` to create new clean allocation + * \param[in] size: Size of new memory to reallocate + * \return Pointer to allocated memory on success, `NULL` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void* +lwmem_realloc(void* ptr, size_t size) { + return lwmem_realloc_ex(NULL, NULL, ptr, size); +} + +/** + * \note This is a wrapper for \ref lwmem_realloc_s_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] ptr2ptr: Pointer to pointer to allocated memory. Must not be set to `NULL`. + * If reallocation is successful, it modifies pointer's pointing address, + * or sets it to `NULL` in case of `free` operation + * \param[in] size: New requested size in bytes + * \return `1` if successfully reallocated, `0` otherwise + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +int +lwmem_realloc_s(void** ptr2ptr, size_t size) { + return lwmem_realloc_s_ex(NULL, NULL, ptr2ptr, size); +} + +/** + * \note This is a wrapper for \ref lwmem_free_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] ptr: Memory to free. `NULL` pointer is valid input + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void +lwmem_free(void* ptr) { + lwmem_free_ex(NULL, (ptr)); +} + +/** + * \note This is a wrapper for \ref lwmem_free_s_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] ptr2ptr: Pointer to pointer to allocated memory. + * When set to non `NULL`, pointer is freed and set to `NULL` + * \note This function is thread safe when \ref LWMEM_CFG_OS is enabled + */ +void +lwmem_free_s(void** ptr2ptr) { + lwmem_free_s_ex(NULL, (ptr2ptr)); +} + +/** + * \note This is a wrapper for \ref lwmem_get_size_ex function. + * It operates in default LwMEM instance and uses first available region for memory operations + * \param[in] ptr: Pointer to allocated memory + * \return Block size for user in units of bytes + */ +size_t +lwmem_get_size(void* ptr) { + return lwmem_get_size_ex(NULL, ptr); +} + +#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ + +/* Part of library used ONLY for LWMEM_DEV purposes */ +/* To validate and test library */ + +#if defined(LWMEM_DEV) && LWMEM_CFG_FULL && !__DOXYGEN__ + +#include +#include + +/* Temporary variable for lwmem save */ +static lwmem_t lwmem_temp; +static lwmem_region_t* regions_orig; +static lwmem_region_t* regions_temp; +static size_t regions_count; + +static lwmem_region_t* +create_regions(size_t count, size_t size) { + lwmem_region_t* regions; + lwmem_region_t tmp; + + /* + * Allocate pointer structure + * + * Length 1 entry more, to set default values for NULL entry + */ + regions = calloc(count + 1, sizeof(*regions)); + if (regions == NULL) { + return NULL; + } + + /* Allocate memory for regions */ + for (size_t i = 0; i < count; ++i) { + regions[i].size = size; + regions[i].start_addr = malloc(regions[i].size); + if (regions[i].start_addr == NULL) { + return NULL; + } + } + regions[count].size = 0; + regions[count].start_addr = NULL; + + /* Sort regions, make sure they grow linearly */ + for (size_t x = 0; x < count; ++x) { + for (size_t y = 0; y < count; ++y) { + if (regions[x].start_addr < regions[y].start_addr) { + memcpy(&tmp, ®ions[x], sizeof(regions[x])); + memcpy(®ions[x], ®ions[y], sizeof(regions[x])); + memcpy(®ions[y], &tmp, sizeof(regions[x])); + } + } + } + + return regions; +} + +static void +print_block(size_t i, lwmem_block_t* block) { + size_t is_free, block_size; + + is_free = (block->size & LWMEM_ALLOC_BIT) == 0 && block != &lwmem_default.start_block_first_use && block->size > 0; + block_size = block->size & ~LWMEM_ALLOC_BIT; + + printf("| %5d | %16p | %6d | %4d | %16d |", (int)i, (void*)block, (int)is_free, (int)block_size, + (int)(is_free ? (block_size - LWMEM_BLOCK_META_SIZE) : 0)); + if (block == &lwmem_default.start_block_first_use) { + printf(" Start block "); + } else if (block_size == 0) { + printf(" End of region "); + } else if (is_free) { + printf(" Free block "); + } else if (!is_free) { + printf(" Allocated block "); + } else { + printf(" "); + } + printf("|\r\n"); +} + +void +lwmem_debug_print(uint8_t print_alloc, uint8_t print_free) { + size_t block_size; + lwmem_block_t* block; + + (void)print_alloc; + (void)print_free; + + printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); + printf("| Block | Address | IsFree | Size | MaxUserAllocSize | Meta |\r\n"); + printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); + + block = &lwmem_default.start_block_first_use; + print_block(0, &lwmem_default.start_block_first_use); + printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); + for (size_t i = 0, j = 1; i < regions_count; ++i) { + block = regions_orig[i].start_addr; + + /* Print all blocks */ + for (;; ++j) { + block_size = block->size & ~LWMEM_ALLOC_BIT; + + print_block(j, block); + + /* Get next block */ + block = (void*)(LWMEM_TO_BYTE_PTR(block) + block_size); + if (block_size == 0) { + break; + } + } + printf("|-------|------------------|--------|------|------------------|-----------------|\r\n"); + } +} + +uint8_t +lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size) { + regions_orig = create_regions(count, size); + regions_temp = create_regions(count, size); + + if (regions_orig == NULL || regions_temp == NULL) { + return 0; + } + regions_count = count; + *regs_out = regions_orig; + + return 1; +} + +void +lwmem_debug_save_state(void) { + memcpy(&lwmem_temp, &lwmem_default, sizeof(lwmem_temp)); + for (size_t i = 0; i < regions_count; ++i) { + memcpy(regions_temp[i].start_addr, regions_orig[i].start_addr, regions_temp[i].size); + } + printf(" -- > Current state saved!\r\n"); +} + +void +lwmem_debug_restore_to_saved(void) { + memcpy(&lwmem_default, &lwmem_temp, sizeof(lwmem_temp)); + for (size_t i = 0; i < regions_count; ++i) { + memcpy(regions_orig[i].start_addr, regions_temp[i].start_addr, regions_temp[i].size); + } + printf(" -- > State restored to last saved!\r\n"); +} + +void +lwmem_debug_test_region(void* region_start, size_t region_size, uint8_t** region_start_calc, size_t* region_size_calc) { + lwmem_region_t region = { + .start_addr = region_start, + .size = region_size, + }; + prv_get_region_addr_size(®ion, region_start_calc, region_size_calc); +} + +#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ diff --git a/User/system/sgl/mm/lwmem/lwmem.h b/User/system/sgl/mm/lwmem/lwmem.h new file mode 100644 index 0000000..db96bb4 --- /dev/null +++ b/User/system/sgl/mm/lwmem/lwmem.h @@ -0,0 +1,160 @@ +/** + * \file lwmem.h + * \brief Lightweight dynamic memory manager + */ + +/* + * Copyright (c) 2024 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.2.1 + */ +#ifndef LWMEM_HDR_H +#define LWMEM_HDR_H + +#include +#include +#include +#include "lwmem_opt.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \defgroup LWMEM Lightweight dynamic memory manager + * \brief Lightweight dynamic memory manager + * \{ + */ + +/** + * \brief Get size of statically allocated array + * \param[in] x: Object to get array size of + * \return Number of elements in array + */ +#define LWMEM_ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) + +/** + * \brief Memory block structure + */ +typedef struct lwmem_block { + struct lwmem_block* next; /*!< Next free memory block on linked list. + Set to \ref LWMEM_BLOCK_ALLOC_MARK when block is allocated and in use */ + size_t size; /*!< Size of block, including metadata part. + MSB bit is set to `1` when block is allocated and in use, + or `0` when block is considered free */ +} lwmem_block_t; + +/** + * \brief Statistics structure + */ +typedef struct { + uint32_t mem_size_bytes; /*!< Total memory size of all regions combined */ + uint32_t mem_available_bytes; /*!< Free memory available for allocation */ + uint32_t minimum_ever_mem_available_bytes; /*!< Minimum amount of total free memory there has been + in the heap since the system booted. */ + uint32_t nr_alloc; /*!< Number of all allocated blocks in single instance */ + uint32_t nr_free; /*!< Number of frees in the LwMEM instance */ +} lwmem_stats_t; + +/** + * \brief LwMEM main structure + */ +typedef struct lwmem { + size_t mem_available_bytes; /*!< Memory size available for allocation */ +#if LWMEM_CFG_FULL + lwmem_block_t start_block; /*!< Holds beginning of memory allocation regions */ + lwmem_block_t* end_block; /*!< Pointer to the last memory location in regions linked list */ + size_t mem_regions_count; /*!< Number of regions used for allocation */ +#else + uint8_t* mem_next_available_ptr; /*!< Pointer for next allocation */ + uint8_t is_initialized; /*!< Set to `1` when initialized */ +#endif + +#if LWMEM_CFG_OS || __DOXYGEN__ + LWMEM_CFG_OS_MUTEX_HANDLE mutex; /*!< System mutex for OS */ +#endif /* LWMEM_CFG_OS || __DOXYGEN__ */ +#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ + lwmem_stats_t stats; /*!< Statistics */ +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ +#if defined(LWMEM_DEV) && !__DOXYGEN__ + lwmem_block_t start_block_first_use; /*!< Value of start block for very first time. + This is used only during validation process and is removed in final use */ +#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ +} lwmem_t; + +/** + * \brief Memory region descriptor + */ +typedef struct { + void* start_addr; /*!< Region start address */ + size_t size; /*!< Size of region in units of bytes */ +} lwmem_region_t; + +size_t lwmem_assignmem_ex(lwmem_t* lwobj, const lwmem_region_t* regions); +void* lwmem_malloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t size); +void* lwmem_calloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, const size_t nitems, const size_t size); +#if LWMEM_CFG_FULL || __DOXYGEN__ +void* lwmem_realloc_ex(lwmem_t* lwobj, const lwmem_region_t* region, void* const ptr, const size_t size); +int lwmem_realloc_s_ex(lwmem_t* lwobj, const lwmem_region_t* region, void** const ptr, const size_t size); +void lwmem_free_ex(lwmem_t* lwobj, void* const ptr); +void lwmem_free_s_ex(lwmem_t* lwobj, void** const ptr); +size_t lwmem_get_size_ex(lwmem_t* lwobj, void* ptr); +#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ +#if LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ +void lwmem_get_stats_ex(lwmem_t* lwobj, lwmem_stats_t* stats); +void lwmem_get_size(lwmem_stats_t* stats); +#endif /* LWMEM_CFG_ENABLE_STATS || __DOXYGEN__ */ + +size_t lwmem_assignmem(const lwmem_region_t* regions); +void* lwmem_malloc(size_t size); +void* lwmem_calloc(size_t nitems, size_t size); + +#if LWMEM_CFG_FULL || __DOXYGEN__ +void* lwmem_realloc(void* ptr, size_t size); +int lwmem_realloc_s(void** ptr2ptr, size_t size); +void lwmem_free(void* ptr); +void lwmem_free_s(void** ptr2ptr); +size_t lwmem_get_size(void* ptr); +#endif /* LWMEM_CFG_FULL || __DOXYGEN__ */ + +#if defined(LWMEM_DEV) && !__DOXYGEN__ +unsigned char lwmem_debug_create_regions(lwmem_region_t** regs_out, size_t count, size_t size); +void lwmem_debug_save_state(void); +void lwmem_debug_restore_to_saved(void); +void lwmem_debug_print(unsigned char print_alloc, unsigned char print_free); +void lwmem_debug_test_region(void* region_start, size_t region_size, uint8_t** region_start_calc, + size_t* region_size_calc); +#endif /* defined(LWMEM_DEV) && !__DOXYGEN__ */ + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWMEM_HDR_H */ diff --git a/User/system/sgl/mm/lwmem/lwmem_opt.h b/User/system/sgl/mm/lwmem/lwmem_opt.h new file mode 100644 index 0000000..8739238 --- /dev/null +++ b/User/system/sgl/mm/lwmem/lwmem_opt.h @@ -0,0 +1,156 @@ +/** + * \file lwmem_opt.h + * \brief LwMEM options + */ + +/* + * Copyright (c) 2024 Tilen MAJERLE + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * This file is part of LwMEM - Lightweight dynamic memory manager library. + * + * Author: Tilen MAJERLE + * Version: v2.2.1 + */ +#ifndef LWMEM_OPT_HDR_H +#define LWMEM_OPT_HDR_H + +/* Uncomment to ignore user options (or set macro in compiler flags) */ +/* #define LWMEM_IGNORE_USER_OPTS */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \defgroup LWMEM_OPT Configuration + * \brief LwMEM options + * \{ + */ + +/** + * \brief Enables `1` or disables `0` operating system support in the library + * + * \note When `LWMEM_CFG_OS` is enabled, user must implement functions in \ref LWMEM_SYS group. + */ +#ifndef LWMEM_CFG_OS +#define LWMEM_CFG_OS 0 +#endif + +/** + * \brief Mutex handle type + * + * \note This value must be set in case \ref LWMEM_CFG_OS is set to `1`. + * If data type is not known to compiler, include header file with + * definition before you define handle type + */ +#ifndef LWMEM_CFG_OS_MUTEX_HANDLE +#define LWMEM_CFG_OS_MUTEX_HANDLE void* +#endif + +/** + * \brief Number of bits to align memory address and memory size + * + * Some CPUs do not offer unaligned memory access (Cortex-M0 as an example) + * therefore it is important to have alignment of data addresses and potentialy length of data + * + * \note This value must be a power of `2` for number of bytes. + * Usually alignment of `4` bytes fits to all processors. + */ +#ifndef LWMEM_CFG_ALIGN_NUM +#define LWMEM_CFG_ALIGN_NUM 4 +#endif + +/** + * \brief Enables `1` or disables `0` full memory management support. + * + * When enabled (default config), library supports allocation, reallocation and freeing of the memory. + * - Memory [c]allocation + * - Memory reallocation + * - Memory allocation in user defined memory regions + * - Memory freeing + * + * When disabled, library only supports allocation and does not provide any other service. + * - Its purpose is for memory allocation at the start of firmware initialization only + * + * \note When disabled, statistics functionaltiy is not available + * and only one region is supported (for now, may be updated later). + * API to allocate memory remains the same as for full configuration. + */ +#ifndef LWMEM_CFG_FULL +#define LWMEM_CFG_FULL 1 +#endif + +/** + * \brief Enables `1` or disables `0` memory cleanup on free operation (or realloc). + * + * It resets unused memory to `0x00` and prevents other applications seeing old data. + * It is disabled by default since it has performance penalties. + */ +#ifndef LWMEM_CFG_CLEAN_MEMORY +#define LWMEM_CFG_CLEAN_MEMORY 0 +#endif + +/** + * \brief Enables `1` or disables `0` statistics in the library + * + */ +#ifndef LWMEM_CFG_ENABLE_STATS +#define LWMEM_CFG_ENABLE_STATS 0 +#endif + +/** + * \brief Memory set function + * + * \note Function footprint is the same as \ref memset + */ +#ifndef LWMEM_MEMSET +#define LWMEM_MEMSET(dst, val, len) memset((dst), (val), (len)) +#endif + +/** + * \brief Memory copy function + * + * \note Function footprint is the same as \ref memcpy + */ +#ifndef LWMEM_MEMCPY +#define LWMEM_MEMCPY(dst, src, len) memcpy((dst), (src), (len)) +#endif + +/** + * \brief Memory move function + * + * \note Function footprint is the same as \ref memmove + */ +#ifndef LWMEM_MEMMOVE +#define LWMEM_MEMMOVE(dst, src, len) memmove((dst), (src), (len)) +#endif + +/** + * \} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LWMEM_OPT_HDR_H */ diff --git a/User/system/sgl/mm/lwmem/sgl_mm.c b/User/system/sgl/mm/lwmem/sgl_mm.c new file mode 100644 index 0000000..c648fbd --- /dev/null +++ b/User/system/sgl/mm/lwmem/sgl_mm.c @@ -0,0 +1,137 @@ +/* source/mm/lwmem/sgl_mm.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include "lwmem.h" +#include +#include + + +static sgl_mm_monitor_t mem = { + .total_size = 0, + .free_size = 0, + .used_size = 0, +}; + + +/** + * @brief initialize memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_init(void *mem_start, size_t len) +{ + lwmem_region_t lwmem[] = { + {.start_addr = mem_start, .size = len,}, + { NULL, 0 }, + }; + + lwmem_assignmem(lwmem); + mem.total_size += len; +} + + +/** + * @brief add memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_add_pool(void *mem_start, size_t len) +{ + lwmem_region_t lwmem[] = { + {.start_addr = mem_start, .size = len,}, + { NULL, 0 }, + }; + + lwmem_assignmem(lwmem); + mem.total_size += len; +} + + +/** + * @brief memory alloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * + * @param size request size of memory + * + * @return point to request memory address +*/ +void* sgl_malloc(size_t size) +{ + void *ret = lwmem_malloc(size); + if(ret == NULL) { + SGL_LOG_ERROR("out of memory"); + return NULL; + } + + mem.used_size += lwmem_get_size(ret); + + return ret; +} + + +/** + * @brief memory realloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * @param p the pointer of request size of memory + * @param size request size of memory + */ +void* sgl_realloc(void *p, size_t size) +{ + void *ret = lwmem_realloc(p, size); + if(ret == NULL) { + SGL_LOG_ERROR("out of memory"); + return NULL; + } + + mem.used_size += size; + + return ret; +} + + +/** + * @brief memory free + * + * @param p the pointer of request size of memory + * + * @return none +*/ +void sgl_free(void *p) +{ + mem.used_size -= lwmem_get_size(p); + lwmem_free(p); +} + + +sgl_mm_monitor_t sgl_mm_get_monitor(void) +{ + int integer = (mem.used_size * 100) / mem.total_size; + int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100); + mem.used_rate = integer << 8 | decimal; + mem.free_size = mem.total_size - mem.used_size; + + return mem; +} diff --git a/User/system/sgl/mm/other/sgl_mm.c b/User/system/sgl/mm/other/sgl_mm.c new file mode 100644 index 0000000..9cf4001 --- /dev/null +++ b/User/system/sgl/mm/other/sgl_mm.c @@ -0,0 +1,141 @@ +/* source/mm/other/sgl_mm.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @file sgl_mm.c + * @brief SGL Memory Management - Default (weak) implementations + * + * @warning DO NOT MODIFY THIS FILE! + * + * This file provides default weak implementations of the memory management + * functions. These functions use the standard C library (malloc/free/realloc). + * + * To customize memory management for your platform: + * 1. Create your own implementation file in your project + * 2. Define the same functions WITHOUT the weak attribute + * 3. Your implementation will automatically override these defaults + * + * Functions available for override: + * - void* sgl_mm_alloc(size_t size) + * - void sgl_mm_free(void *ptr) + * - void* sgl_mm_realloc(void *ptr, size_t size) + * + * Example (in your application code): + * @code + * void* sgl_mm_alloc(size_t size) { + * return my_custom_allocator(size); + * } + * @endcode + */ + + +#include +#include +#include +#include +#include +#include + + +static sgl_mm_monitor_t mem = { + .total_size = 0, + .free_size = 0, + .used_size = 0, +}; + + +/** + * @brief initialize memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_init(void *mem_start, size_t len) +{ + mem.total_size += len; +} + + +/** + * @brief add memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_add_pool(void *mem_start, size_t len) +{ + + mem.total_size += len; +} + + +/** + * @brief memory alloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * + * @param size request size of memory + * + * @return point to request memory address +*/ +sgl_weak_fn void* sgl_malloc(size_t size) +{ + void *p = malloc(size); + memset(p, 0, size); + return p; +} + + +/** + * @brief memory realloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * @param p the pointer of request size of memory + * @param size request size of memory + */ +sgl_weak_fn void* sgl_realloc(void *p, size_t size) +{ + return realloc(p, size); +} + + +/** + * @brief memory free + * + * @param p the pointer of request size of memory + * + * @return none +*/ +sgl_weak_fn void sgl_free(void *p) +{ + //mem.used_size -= ; + free(p); +} + + +sgl_mm_monitor_t sgl_mm_get_monitor(void) +{ + int integer = (mem.used_size * 100) / mem.total_size; + int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100); + mem.used_rate = integer << 8 | decimal; + mem.free_size = mem.total_size - mem.used_size; + + return mem; +} diff --git a/User/system/sgl/mm/tlsf/sgl_mm.c b/User/system/sgl/mm/tlsf/sgl_mm.c new file mode 100644 index 0000000..89b851d --- /dev/null +++ b/User/system/sgl/mm/tlsf/sgl_mm.c @@ -0,0 +1,128 @@ +/* source/mm/tlsf/sgl_mm.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "tlsf.h" +#include +#include +#include +#include + + +static tlsf_t mem_tlsf; +static sgl_mm_monitor_t mem = { + .total_size = 0, + .free_size = 0, + .used_size = 0, +}; + + +/** + * @brief initialize memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_init(void *mem_start, size_t len) +{ + mem_tlsf = tlsf_create_with_pool(mem_start, len); + mem.total_size += len; +} + + +/** + * @brief add memory pool + * @param mem_start start address of memory pool + * @param len length of memory pool + */ +void sgl_mm_add_pool(void *mem_start, size_t len) +{ + tlsf_add_pool(mem_tlsf, mem_start, len); + mem.total_size += len; +} + + +/** + * @brief memory alloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * + * @param size request size of memory + * + * @return point to request memory address +*/ +void* sgl_malloc(size_t size) +{ + void *ret = tlsf_malloc(mem_tlsf, size); + if(ret == NULL) { + SGL_LOG_ERROR("out of memory"); + return NULL; + } + + mem.used_size += size; + return ret; +} + + +/** + * @brief memory realloc, the function is unsafe, you should ensure that + * the requested size is smaller than the free size of memory + * @param p the pointer of request size of memory + * @param size request size of memory + */ +void* sgl_realloc(void *p, size_t size) +{ + void *ret = tlsf_realloc(mem_tlsf, p, size); + if(ret == NULL) { + SGL_LOG_ERROR("out of memory"); + return NULL; + } + + mem.used_size += size; + + return ret; +} + + +/** + * @brief memory free + * + * @param p the pointer of request size of memory + * + * @return none +*/ +void sgl_free(void *p) +{ + mem.used_size -= tlsf_block_size(p); + + tlsf_free(mem_tlsf, p); +} + + +sgl_mm_monitor_t sgl_mm_get_monitor(void) +{ + int integer = (mem.used_size * 100) / mem.total_size; + int decimal = (mem.used_size * 10000) / mem.total_size - (integer * 100); + mem.used_rate = integer << 8 | decimal; + mem.free_size = mem.total_size - mem.used_size; + + return mem; +} diff --git a/User/system/sgl/mm/tlsf/tlsf.c b/User/system/sgl/mm/tlsf/tlsf.c new file mode 100644 index 0000000..13344ff --- /dev/null +++ b/User/system/sgl/mm/tlsf/tlsf.c @@ -0,0 +1,1265 @@ +#include +#include +#include +#include +#include +#include "tlsf.h" + + +#if defined(__cplusplus) +#define tlsf_decl inline +#else +#define tlsf_decl static +#endif + +/* +** Architecture-specific bit manipulation routines. +** +** TLSF achieves O(1) cost for malloc and free operations by limiting +** the search for a free block to a free list of guaranteed size +** adequate to fulfill the request, combined with efficient free list +** queries using bitmasks and architecture-specific bit-manipulation +** routines. +** +** Most modern processors provide instructions to count leading zeroes +** in a word, find the lowest and highest set bit, etc. These +** specific implementations will be used when available, falling back +** to a reasonably efficient generic implementation. +** +** NOTE: TLSF spec relies on ffs/fls returning value 0..31. +** ffs/fls return 1-32 by default, returning 0 for error. +*/ + +/* +** Detect whether or not we are building for a 32- or 64-bit (LP/LLP) +** architecture. There is no reliable portable method at compile-time. +*/ +#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) \ + || defined (_WIN64) || defined (__LP64__) || defined (__LLP64__) +#define TLSF_64BIT +#endif + +/* +** gcc 3.4 and above have builtin support, specialized for architecture. +** Some compilers masquerade as gcc; patchlevel test filters them out. +*/ +#if defined (__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \ + && defined (__GNUC_PATCHLEVEL__) + +#if defined (__SNC__) +/* SNC for Playstation 3. */ + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __builtin_clz(reverse); + return bit - 1; +} + +#else + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + return __builtin_ffs(word) - 1; +} + +#endif + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __builtin_clz(word) : 0; + return bit - 1; +} + +#elif defined (_MSC_VER) && (_MSC_VER >= 1400) && (defined (_M_IX86) || defined (_M_X64)) +/* Microsoft Visual C++ support on x86/X64 architectures. */ + +#include + +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +tlsf_decl int tlsf_fls(unsigned int word) +{ + unsigned long index; + return _BitScanReverse(&index, word) ? index : -1; +} + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + unsigned long index; + return _BitScanForward(&index, word) ? index : -1; +} + +#elif defined (_MSC_VER) && defined (_M_PPC) +/* Microsoft Visual C++ support on PowerPC architectures. */ + +#include + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = 32 - _CountLeadingZeros(word); + return bit - 1; +} + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - _CountLeadingZeros(reverse); + return bit - 1; +} + +#elif defined (__ARMCC_VERSION) +/* RealView Compilation Tools for ARM */ + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __clz(reverse); + return bit - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __clz(word) : 0; + return bit - 1; +} + +#elif defined (__ghs__) +/* Green Hills support for PowerPC */ + +#include + +tlsf_decl int tlsf_ffs(unsigned int word) +{ + const unsigned int reverse = word & (~word + 1); + const int bit = 32 - __CLZ32(reverse); + return bit - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + const int bit = word ? 32 - __CLZ32(word) : 0; + return bit - 1; +} + +#else +/* Fall back to generic implementation. */ + +tlsf_decl int tlsf_fls_generic(unsigned int word) +{ + int bit = 32; + + if (!word) bit -= 1; + if (!(word & 0xffff0000)) { word <<= 16; bit -= 16; } + if (!(word & 0xff000000)) { word <<= 8; bit -= 8; } + if (!(word & 0xf0000000)) { word <<= 4; bit -= 4; } + if (!(word & 0xc0000000)) { word <<= 2; bit -= 2; } + if (!(word & 0x80000000)) { word <<= 1; bit -= 1; } + + return bit; +} + +/* Implement ffs in terms of fls. */ +tlsf_decl int tlsf_ffs(unsigned int word) +{ + return tlsf_fls_generic(word & (~word + 1)) - 1; +} + +tlsf_decl int tlsf_fls(unsigned int word) +{ + return tlsf_fls_generic(word) - 1; +} + +#endif + +/* Possibly 64-bit version of tlsf_fls. */ +#if defined (TLSF_64BIT) +tlsf_decl int tlsf_fls_sizet(size_t size) +{ + int high = (int)(size >> 32); + int bits = 0; + if (high) + { + bits = 32 + tlsf_fls(high); + } + else + { + bits = tlsf_fls((int)size & 0xffffffff); + + } + return bits; +} +#else +#define tlsf_fls_sizet tlsf_fls +#endif + +#undef tlsf_decl + +/* +** Constants. +*/ + +/* Public constants: may be modified. */ +enum tlsf_public +{ + /* log2 of number of linear subdivisions of block sizes. Larger + ** values require more memory in the control structure. Values of + ** 4 or 5 are typical. + */ + SL_INDEX_COUNT_LOG2 = 5, +}; + +/* Private constants: do not modify. */ +enum tlsf_private +{ +#if defined (TLSF_64BIT) + /* All allocation sizes and addresses are aligned to 8 bytes. */ + ALIGN_SIZE_LOG2 = 3, +#else + /* All allocation sizes and addresses are aligned to 4 bytes. */ + ALIGN_SIZE_LOG2 = 2, +#endif + ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2), + + /* + ** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits. + ** However, because we linearly subdivide the second-level lists, and + ** our minimum size granularity is 4 bytes, it doesn't make sense to + ** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4, + ** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be + ** trying to split size ranges into more slots than we have available. + ** Instead, we calculate the minimum threshold size, and place all + ** blocks below that size into the 0th first-level list. + */ + +#if defined (TLSF_64BIT) + /* + ** TODO: We can increase this to support larger sizes, at the expense + ** of more overhead in the TLSF structure. + */ + FL_INDEX_MAX = 32, //MAX 4GB +#else + FL_INDEX_MAX = CONFIG_SGL_FL_INDEX_MAX, +#endif + SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2), + FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2), + FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1), + + SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT), +}; + +/* +** Cast and min/max macros. +*/ + +#define tlsf_cast(t, exp) ((t) (exp)) +#define tlsf_min(a, b) ((a) < (b) ? (a) : (b)) +#define tlsf_max(a, b) ((a) > (b) ? (a) : (b)) + +/* +** Set assert macro, if it has not been provided by the user. +*/ +#if CONFIG_SGL_DEBUG +#define tlsf_assert SGL_ASSERT +#else +#define tlsf_assert +#endif + +/* +** Static assertion mechanism. +*/ + +#define _tlsf_glue2(x, y) x ## y +#define _tlsf_glue(x, y) _tlsf_glue2(x, y) +#define tlsf_static_assert(exp) \ + typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1] + +/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */ +tlsf_static_assert(sizeof(int) * CHAR_BIT == 32); +tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32); +tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64); + +/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */ +tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT); + +/* Ensure we've properly tuned our sizes. */ +tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT); + +/* +** Data structures and associated constants. +*/ + +/* +** Block header structure. +** +** There are several implementation subtleties involved: +** - The prev_phys_block field is only valid if the previous block is free. +** - The prev_phys_block field is actually stored at the end of the +** previous block. It appears at the beginning of this structure only to +** simplify the implementation. +** - The next_free / prev_free fields are only valid if the block is free. +*/ +typedef struct block_header_t +{ + /* Points to the previous physical block. */ + struct block_header_t* prev_phys_block; + + /* The size of this block, excluding the block header. */ + size_t size; + + /* Next and previous free blocks. */ + struct block_header_t* next_free; + struct block_header_t* prev_free; +} block_header_t; + +/* +** Since block sizes are always at least a multiple of 4, the two least +** significant bits of the size field are used to store the block status: +** - bit 0: whether block is busy or free +** - bit 1: whether previous block is busy or free +*/ +static const size_t block_header_free_bit = 1 << 0; +static const size_t block_header_prev_free_bit = 1 << 1; + +/* +** The size of the block header exposed to used blocks is the size field. +** The prev_phys_block field is stored *inside* the previous free block. +*/ +static const size_t block_header_overhead = sizeof(size_t); + +/* User data starts directly after the size field in a used block. */ +static const size_t block_start_offset = + offsetof(block_header_t, size) + sizeof(size_t); + +/* +** A free block must be large enough to store its header minus the size of +** the prev_phys_block field, and no larger than the number of addressable +** bits for FL_INDEX. +*/ +static const size_t block_size_min = + sizeof(block_header_t) - sizeof(block_header_t*); +static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX; + + +/* The TLSF control structure. */ +typedef struct control_t +{ + /* Empty lists point at this block to indicate they are free. */ + block_header_t block_null; + + /* Bitmaps for free lists. */ + unsigned int fl_bitmap; + unsigned int sl_bitmap[FL_INDEX_COUNT]; + + /* Head of free lists. */ + block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT]; +} control_t; + +/* A type used for casting when doing pointer arithmetic. */ +typedef ptrdiff_t tlsfptr_t; + +/* +** block_header_t member functions. +*/ + +static size_t block_size(const block_header_t* block) +{ + return block->size & ~(block_header_free_bit | block_header_prev_free_bit); +} + +static void block_set_size(block_header_t* block, size_t size) +{ + const size_t oldsize = block->size; + block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit)); +} + +static int block_is_last(const block_header_t* block) +{ + return block_size(block) == 0; +} + +static int block_is_free(const block_header_t* block) +{ + return tlsf_cast(int, block->size & block_header_free_bit); +} + +static void block_set_free(block_header_t* block) +{ + block->size |= block_header_free_bit; +} + +static void block_set_used(block_header_t* block) +{ + block->size &= ~block_header_free_bit; +} + +static int block_is_prev_free(const block_header_t* block) +{ + return tlsf_cast(int, block->size & block_header_prev_free_bit); +} + +static void block_set_prev_free(block_header_t* block) +{ + block->size |= block_header_prev_free_bit; +} + +static void block_set_prev_used(block_header_t* block) +{ + block->size &= ~block_header_prev_free_bit; +} + +static block_header_t* block_from_ptr(const void* ptr) +{ + return tlsf_cast(block_header_t*, + tlsf_cast(unsigned char*, ptr) - block_start_offset); +} + +static void* block_to_ptr(const block_header_t* block) +{ + return tlsf_cast(void*, + tlsf_cast(unsigned char*, block) + block_start_offset); +} + +/* Return location of next block after block of given size. */ +static block_header_t* offset_to_block(const void* ptr, size_t size) +{ + return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size); +} + +/* Return location of previous block. */ +static block_header_t* block_prev(const block_header_t* block) +{ + tlsf_assert(block_is_prev_free(block) && "previous block must be free"); + return block->prev_phys_block; +} + +/* Return location of next existing block. */ +static block_header_t* block_next(const block_header_t* block) +{ + block_header_t* next = offset_to_block(block_to_ptr(block), + block_size(block) - block_header_overhead); + tlsf_assert(!block_is_last(block)); + return next; +} + +/* Link a new block with its physical neighbor, return the neighbor. */ +static block_header_t* block_link_next(block_header_t* block) +{ + block_header_t* next = block_next(block); + next->prev_phys_block = block; + return next; +} + +static void block_mark_as_free(block_header_t* block) +{ + /* Link the block to the next block, first. */ + block_header_t* next = block_link_next(block); + block_set_prev_free(next); + block_set_free(block); +} + +static void block_mark_as_used(block_header_t* block) +{ + block_header_t* next = block_next(block); + block_set_prev_used(next); + block_set_used(block); +} + +static size_t align_up(size_t x, size_t align) +{ + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return (x + (align - 1)) & ~(align - 1); +} + +static size_t align_down(size_t x, size_t align) +{ + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return x - (x & (align - 1)); +} + +static void* align_ptr(const void* ptr, size_t align) +{ + const tlsfptr_t aligned = + (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1); + tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two"); + return tlsf_cast(void*, aligned); +} + +/* +** Adjust an allocation size to be aligned to word size, and no smaller +** than internal minimum. +*/ +static size_t adjust_request_size(size_t size, size_t align) +{ + size_t adjust = 0; + if (size) + { + const size_t aligned = align_up(size, align); + + /* aligned sized must not exceed block_size_max or we'll go out of bounds on sl_bitmap */ + if (aligned < block_size_max) + { + adjust = tlsf_max(aligned, block_size_min); + } + } + return adjust; +} + +/* +** TLSF utility functions. In most cases, these are direct translations of +** the documentation found in the white paper. +*/ + +static void mapping_insert(size_t size, int* fli, int* sli) +{ + int fl, sl; + if (size < SMALL_BLOCK_SIZE) + { + /* Store small blocks in first list. */ + fl = 0; + sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT); + } + else + { + fl = tlsf_fls_sizet(size); + sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2); + fl -= (FL_INDEX_SHIFT - 1); + } + *fli = fl; + *sli = sl; +} + +/* This version rounds up to the next block size (for allocations) */ +static void mapping_search(size_t size, int* fli, int* sli) +{ + if (size >= SMALL_BLOCK_SIZE) + { + const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1; + size += round; + } + mapping_insert(size, fli, sli); +} + +static block_header_t* search_suitable_block(control_t* control, int* fli, int* sli) +{ + int fl = *fli; + int sl = *sli; + + /* + ** First, search for a block in the list associated with the given + ** fl/sl index. + */ + unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl); + if (!sl_map) + { + /* No block exists. Search in the next largest first-level list. */ + const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1)); + if (!fl_map) + { + /* No free blocks available, memory has been exhausted. */ + return 0; + } + + fl = tlsf_ffs(fl_map); + *fli = fl; + sl_map = control->sl_bitmap[fl]; + } + tlsf_assert(sl_map && "internal error - second level bitmap is null"); + sl = tlsf_ffs(sl_map); + *sli = sl; + + /* Return the first block in the free list. */ + return control->blocks[fl][sl]; +} + +/* Remove a free block from the free list.*/ +static void remove_free_block(control_t* control, block_header_t* block, int fl, int sl) +{ + block_header_t* prev = block->prev_free; + block_header_t* next = block->next_free; + tlsf_assert(prev && "prev_free field can not be null"); + tlsf_assert(next && "next_free field can not be null"); + next->prev_free = prev; + prev->next_free = next; + + /* If this block is the head of the free list, set new head. */ + if (control->blocks[fl][sl] == block) + { + control->blocks[fl][sl] = next; + + /* If the new head is null, clear the bitmap. */ + if (next == &control->block_null) + { + control->sl_bitmap[fl] &= ~(1U << sl); + + /* If the second bitmap is now empty, clear the fl bitmap. */ + if (!control->sl_bitmap[fl]) + { + control->fl_bitmap &= ~(1U << fl); + } + } + } +} + +/* Insert a free block into the free block list. */ +static void insert_free_block(control_t* control, block_header_t* block, int fl, int sl) +{ + block_header_t* current = control->blocks[fl][sl]; + tlsf_assert(current && "free list cannot have a null entry"); + tlsf_assert(block && "cannot insert a null entry into the free list"); + block->next_free = current; + block->prev_free = &control->block_null; + current->prev_free = block; + + tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE) + && "block not aligned properly"); + /* + ** Insert the new block at the head of the list, and mark the first- + ** and second-level bitmaps appropriately. + */ + control->blocks[fl][sl] = block; + control->fl_bitmap |= (1U << fl); + control->sl_bitmap[fl] |= (1U << sl); +} + +/* Remove a given block from the free list. */ +static void block_remove(control_t* control, block_header_t* block) +{ + int fl, sl; + mapping_insert(block_size(block), &fl, &sl); + remove_free_block(control, block, fl, sl); +} + +/* Insert a given block into the free list. */ +static void block_insert(control_t* control, block_header_t* block) +{ + int fl, sl; + mapping_insert(block_size(block), &fl, &sl); + insert_free_block(control, block, fl, sl); +} + +static int block_can_split(block_header_t* block, size_t size) +{ + return block_size(block) >= sizeof(block_header_t) + size; +} + +/* Split a block into two, the second of which is free. */ +static block_header_t* block_split(block_header_t* block, size_t size) +{ + /* Calculate the amount of space left in the remaining block. */ + block_header_t* remaining = + offset_to_block(block_to_ptr(block), size - block_header_overhead); + + const size_t remain_size = block_size(block) - (size + block_header_overhead); + + tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE) + && "remaining block not aligned properly"); + + tlsf_assert(block_size(block) == remain_size + size + block_header_overhead); + block_set_size(remaining, remain_size); + tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size"); + + block_set_size(block, size); + block_mark_as_free(remaining); + + return remaining; +} + +/* Absorb a free block's storage into an adjacent previous free block. */ +static block_header_t* block_absorb(block_header_t* prev, block_header_t* block) +{ + tlsf_assert(!block_is_last(prev) && "previous block can't be last"); + /* Note: Leaves flags untouched. */ + prev->size += block_size(block) + block_header_overhead; + block_link_next(prev); + return prev; +} + +/* Merge a just-freed block with an adjacent previous free block. */ +static block_header_t* block_merge_prev(control_t* control, block_header_t* block) +{ + if (block_is_prev_free(block)) + { + block_header_t* prev = block_prev(block); + tlsf_assert(prev && "prev physical block can't be null"); + tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such"); + block_remove(control, prev); + block = block_absorb(prev, block); + } + + return block; +} + +/* Merge a just-freed block with an adjacent free block. */ +static block_header_t* block_merge_next(control_t* control, block_header_t* block) +{ + block_header_t* next = block_next(block); + tlsf_assert(next && "next physical block can't be null"); + + if (block_is_free(next)) + { + tlsf_assert(!block_is_last(block) && "previous block can't be last"); + block_remove(control, next); + block = block_absorb(block, next); + } + + return block; +} + +/* Trim any trailing block space off the end of a block, return to pool. */ +static void block_trim_free(control_t* control, block_header_t* block, size_t size) +{ + tlsf_assert(block_is_free(block) && "block must be free"); + if (block_can_split(block, size)) + { + block_header_t* remaining_block = block_split(block, size); + block_link_next(block); + block_set_prev_free(remaining_block); + block_insert(control, remaining_block); + } +} + +/* Trim any trailing block space off the end of a used block, return to pool. */ +static void block_trim_used(control_t* control, block_header_t* block, size_t size) +{ + tlsf_assert(!block_is_free(block) && "block must be used"); + if (block_can_split(block, size)) + { + /* If the next block is free, we must coalesce. */ + block_header_t* remaining_block = block_split(block, size); + block_set_prev_used(remaining_block); + + remaining_block = block_merge_next(control, remaining_block); + block_insert(control, remaining_block); + } +} + +static block_header_t* block_trim_free_leading(control_t* control, block_header_t* block, size_t size) +{ + block_header_t* remaining_block = block; + if (block_can_split(block, size)) + { + /* We want the 2nd block. */ + remaining_block = block_split(block, size - block_header_overhead); + block_set_prev_free(remaining_block); + + block_link_next(block); + block_insert(control, block); + } + + return remaining_block; +} + +static block_header_t* block_locate_free(control_t* control, size_t size) +{ + int fl = 0, sl = 0; + block_header_t* block = 0; + + if (size) + { + mapping_search(size, &fl, &sl); + + /* + ** mapping_search can futz with the size, so for excessively large sizes it can sometimes wind up + ** with indices that are off the end of the block array. + ** So, we protect against that here, since this is the only callsite of mapping_search. + ** Note that we don't need to check sl, since it comes from a modulo operation that guarantees it's always in range. + */ + if (fl < FL_INDEX_COUNT) + { + block = search_suitable_block(control, &fl, &sl); + } + } + + if (block) + { + tlsf_assert(block_size(block) >= size); + remove_free_block(control, block, fl, sl); + } + + return block; +} + +static void* block_prepare_used(control_t* control, block_header_t* block, size_t size) +{ + void* p = 0; + if (block) + { + tlsf_assert(size && "size must be non-zero"); + block_trim_free(control, block, size); + block_mark_as_used(block); + p = block_to_ptr(block); + } + return p; +} + +/* Clear structure and point all empty lists at the null block. */ +static void control_construct(control_t* control) +{ + int i, j; + + control->block_null.next_free = &control->block_null; + control->block_null.prev_free = &control->block_null; + + control->fl_bitmap = 0; + for (i = 0; i < FL_INDEX_COUNT; ++i) + { + control->sl_bitmap[i] = 0; + for (j = 0; j < SL_INDEX_COUNT; ++j) + { + control->blocks[i][j] = &control->block_null; + } + } +} + +/* +** Debugging utilities. +*/ + +typedef struct integrity_t +{ + int prev_status; + int status; +} integrity_t; + +#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } } + +static void integrity_walker(void* ptr, size_t size, int used, void* user) +{ + block_header_t* block = block_from_ptr(ptr); + integrity_t* integ = tlsf_cast(integrity_t*, user); + const int this_prev_status = block_is_prev_free(block) ? 1 : 0; + const int this_status = block_is_free(block) ? 1 : 0; + const size_t this_block_size = block_size(block); + + int status = 0; + (void)used; + tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect"); + tlsf_insist(size == this_block_size && "block size incorrect"); + + integ->prev_status = this_status; + integ->status += status; +} + +int tlsf_check(tlsf_t tlsf) +{ + int i, j; + + control_t* control = tlsf_cast(control_t*, tlsf); + int status = 0; + + /* Check that the free lists and bitmaps are accurate. */ + for (i = 0; i < FL_INDEX_COUNT; ++i) + { + for (j = 0; j < SL_INDEX_COUNT; ++j) + { + const int fl_map = control->fl_bitmap & (1U << i); + const int sl_list = control->sl_bitmap[i]; + const int sl_map = sl_list & (1U << j); + const block_header_t* block = control->blocks[i][j]; + + /* Check that first- and second-level lists agree. */ + if (!fl_map) + { + tlsf_insist(!sl_map && "second-level map must be null"); + } + + if (!sl_map) + { + tlsf_insist(block == &control->block_null && "block list must be null"); + continue; + } + + /* Check that there is at least one free block. */ + tlsf_insist(sl_list && "no free blocks in second-level map"); + tlsf_insist(block != &control->block_null && "block should not be null"); + + while (block != &control->block_null) + { + int fli, sli; + tlsf_insist(block_is_free(block) && "block should be free"); + tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced"); + tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced"); + tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free"); + tlsf_insist(block_size(block) >= block_size_min && "block not minimum size"); + + mapping_insert(block_size(block), &fli, &sli); + tlsf_insist(fli == i && sli == j && "block size indexed in wrong list"); + block = block->next_free; + } + } + } + + return status; +} + +#undef tlsf_insist + +static void default_walker(void* ptr, size_t size, int used, void* user) +{ + (void)user; + SGL_LOG_INFO("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, block_from_ptr(ptr)); +} + +void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user) +{ + tlsf_walker pool_walker = walker ? walker : default_walker; + block_header_t* block = + offset_to_block(pool, -(int)block_header_overhead); + + while (block && !block_is_last(block)) + { + pool_walker( + block_to_ptr(block), + block_size(block), + !block_is_free(block), + user); + block = block_next(block); + } +} + +size_t tlsf_block_size(void* ptr) +{ + size_t size = 0; + if (ptr) + { + const block_header_t* block = block_from_ptr(ptr); + size = block_size(block); + } + return size; +} + +int tlsf_check_pool(pool_t pool) +{ + /* Check that the blocks are physically correct. */ + integrity_t integ = { 0, 0 }; + tlsf_walk_pool(pool, integrity_walker, &integ); + + return integ.status; +} + +/* +** Size of the TLSF structures in a given memory block passed to +** tlsf_create, equal to the size of a control_t +*/ +size_t tlsf_size(void) +{ + return sizeof(control_t); +} + +size_t tlsf_align_size(void) +{ + return ALIGN_SIZE; +} + +size_t tlsf_block_size_min(void) +{ + return block_size_min; +} + +size_t tlsf_block_size_max(void) +{ + return block_size_max; +} + +/* +** Overhead of the TLSF structures in a given memory block passed to +** tlsf_add_pool, equal to the overhead of a free block and the +** sentinel block. +*/ +size_t tlsf_pool_overhead(void) +{ + return 2 * block_header_overhead; +} + +size_t tlsf_alloc_overhead(void) +{ + return block_header_overhead; +} + +pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes) +{ + block_header_t* block; + block_header_t* next; + + const size_t pool_overhead = tlsf_pool_overhead(); + const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE); + + if (((ptrdiff_t)mem % ALIGN_SIZE) != 0) + { + SGL_LOG_INFO("tlsf_add_pool: Memory must be aligned by %u bytes.\n", + (unsigned int)ALIGN_SIZE); + return 0; + } + + if (pool_bytes < block_size_min || pool_bytes > block_size_max) + { +#if defined (TLSF_64BIT) + SGL_LOG_INFO("tlsf_add_pool: Memory size must be between 0x%x and 0x%x00 bytes.\n", + (unsigned int)(pool_overhead + block_size_min), + (unsigned int)((pool_overhead + block_size_max) / 256)); +#else + SGL_LOG_INFO("tlsf_add_pool: Memory size must be between %u and %u bytes.\n", + (unsigned int)(pool_overhead + block_size_min), + (unsigned int)(pool_overhead + block_size_max)); +#endif + return 0; + } + + /* + ** Create the main free block. Offset the start of the block slightly + ** so that the prev_phys_block field falls outside of the pool - + ** it will never be used. + */ + block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead); + block_set_size(block, pool_bytes); + block_set_free(block); + block_set_prev_used(block); + block_insert(tlsf_cast(control_t*, tlsf), block); + + /* Split the block to create a zero-size sentinel block. */ + next = block_link_next(block); + block_set_size(next, 0); + block_set_used(next); + block_set_prev_free(next); + + return mem; +} + +void tlsf_remove_pool(tlsf_t tlsf, pool_t pool) +{ + control_t* control = tlsf_cast(control_t*, tlsf); + block_header_t* block = offset_to_block(pool, -(int)block_header_overhead); + + int fl = 0, sl = 0; + + tlsf_assert(block_is_free(block) && "block should be free"); + tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free"); + tlsf_assert(block_size(block_next(block)) == 0 && "next block size should be zero"); + + mapping_insert(block_size(block), &fl, &sl); + remove_free_block(control, block, fl, sl); +} + +/* +** TLSF main interface. +*/ + +#if _DEBUG +int test_ffs_fls() +{ + /* Verify ffs/fls work properly. */ + int rv = 0; + rv += (tlsf_ffs(0) == -1) ? 0 : 0x1; + rv += (tlsf_fls(0) == -1) ? 0 : 0x2; + rv += (tlsf_ffs(1) == 0) ? 0 : 0x4; + rv += (tlsf_fls(1) == 0) ? 0 : 0x8; + rv += (tlsf_ffs(0x80000000) == 31) ? 0 : 0x10; + rv += (tlsf_ffs(0x80008000) == 15) ? 0 : 0x20; + rv += (tlsf_fls(0x80000008) == 31) ? 0 : 0x40; + rv += (tlsf_fls(0x7FFFFFFF) == 30) ? 0 : 0x80; + +#if defined (TLSF_64BIT) + rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100; + rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200; + rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400; +#endif + + if (rv) + { + SGL_LOG_INFO("test_ffs_fls: %x ffs/fls tests failed.\n", rv); + } + return rv; +} +#endif + +tlsf_t tlsf_create(void* mem) +{ +#if _DEBUG + if (test_ffs_fls()) + { + return 0; + } +#endif + + if (((tlsfptr_t)mem % ALIGN_SIZE) != 0) + { + SGL_LOG_INFO("tlsf_create: Memory must be aligned to %u bytes.\n", + (unsigned int)ALIGN_SIZE); + return 0; + } + + control_construct(tlsf_cast(control_t*, mem)); + + return tlsf_cast(tlsf_t, mem); +} + +tlsf_t tlsf_create_with_pool(void* mem, size_t bytes) +{ + tlsf_t tlsf = tlsf_create(mem); + tlsf_add_pool(tlsf, (char*)mem + tlsf_size(), bytes - tlsf_size()); + return tlsf; +} + +void tlsf_destroy(tlsf_t tlsf) +{ + /* Nothing to do. */ + (void)tlsf; +} + +pool_t tlsf_get_pool(tlsf_t tlsf) +{ + return tlsf_cast(pool_t, (char*)tlsf + tlsf_size()); +} + +void* tlsf_malloc(tlsf_t tlsf, size_t size) +{ + control_t* control = tlsf_cast(control_t*, tlsf); + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + block_header_t* block = block_locate_free(control, adjust); + return block_prepare_used(control, block, adjust); +} + +void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size) +{ + control_t* control = tlsf_cast(control_t*, tlsf); + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + + /* + ** We must allocate an additional minimum block size bytes so that if + ** our free block will leave an alignment gap which is smaller, we can + ** trim a leading free block and release it back to the pool. We must + ** do this because the previous physical block is in use, therefore + ** the prev_phys_block field is not valid, and we can't simply adjust + ** the size of that block. + */ + const size_t gap_minimum = sizeof(block_header_t); + const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align); + + /* + ** If alignment is less than or equals base alignment, we're done. + ** If we requested 0 bytes, return null, as tlsf_malloc(0) does. + */ + const size_t aligned_size = (adjust && align > ALIGN_SIZE) ? size_with_gap : adjust; + + block_header_t* block = block_locate_free(control, aligned_size); + + /* This can't be a static assert. */ + tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead); + + if (block) + { + void* ptr = block_to_ptr(block); + void* aligned = align_ptr(ptr, align); + size_t gap = tlsf_cast(size_t, + tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); + + /* If gap size is too small, offset to next aligned boundary. */ + if (gap && gap < gap_minimum) + { + const size_t gap_remain = gap_minimum - gap; + const size_t offset = tlsf_max(gap_remain, align); + const void* next_aligned = tlsf_cast(void*, + tlsf_cast(tlsfptr_t, aligned) + offset); + + aligned = align_ptr(next_aligned, align); + gap = tlsf_cast(size_t, + tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr)); + } + + if (gap) + { + tlsf_assert(gap >= gap_minimum && "gap size too small"); + block = block_trim_free_leading(control, block, gap); + } + } + + return block_prepare_used(control, block, adjust); +} + +void tlsf_free(tlsf_t tlsf, void* ptr) +{ + /* Don't attempt to free a NULL pointer. */ + if (ptr) + { + control_t* control = tlsf_cast(control_t*, tlsf); + block_header_t* block = block_from_ptr(ptr); + tlsf_assert(!block_is_free(block) && "block already marked as free"); + block_mark_as_free(block); + block = block_merge_prev(control, block); + block = block_merge_next(control, block); + block_insert(control, block); + } +} + +/* +** The TLSF block information provides us with enough information to +** provide a reasonably intelligent implementation of realloc, growing or +** shrinking the currently allocated block as required. +** +** This routine handles the somewhat esoteric edge cases of realloc: +** - a non-zero size with a null pointer will behave like malloc +** - a zero size with a non-null pointer will behave like free +** - a request that cannot be satisfied will leave the original buffer +** untouched +** - an extended buffer size will leave the newly-allocated area with +** contents undefined +*/ +void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size) +{ + control_t* control = tlsf_cast(control_t*, tlsf); + void* p = 0; + + /* Zero-size requests are treated as free. */ + if (ptr && size == 0) + { + tlsf_free(tlsf, ptr); + } + /* Requests with NULL pointers are treated as malloc. */ + else if (!ptr) + { + p = tlsf_malloc(tlsf, size); + } + else + { + block_header_t* block = block_from_ptr(ptr); + block_header_t* next = block_next(block); + + const size_t cursize = block_size(block); + const size_t combined = cursize + block_size(next) + block_header_overhead; + const size_t adjust = adjust_request_size(size, ALIGN_SIZE); + + tlsf_assert(!block_is_free(block) && "block already marked as free"); + + /* + ** If the next block is used, or when combined with the current + ** block, does not offer enough space, we must reallocate and copy. + */ + if (adjust > cursize && (!block_is_free(next) || adjust > combined)) + { + p = tlsf_malloc(tlsf, size); + if (p) + { + const size_t minsize = tlsf_min(cursize, size); + memcpy(p, ptr, minsize); + tlsf_free(tlsf, ptr); + } + } + else + { + /* Do we need to expand to the next block? */ + if (adjust > cursize) + { + block_merge_next(control, block); + block_mark_as_used(block); + } + + /* Trim the resulting block and return the original pointer. */ + block_trim_used(control, block, adjust); + p = ptr; + } + } + + return p; +} diff --git a/User/system/sgl/mm/tlsf/tlsf.h b/User/system/sgl/mm/tlsf/tlsf.h new file mode 100644 index 0000000..2f17485 --- /dev/null +++ b/User/system/sgl/mm/tlsf/tlsf.h @@ -0,0 +1,93 @@ +#ifndef INCLUDED_tlsf +#define INCLUDED_tlsf + +/* +** Two Level Segregated Fit memory allocator, version 3.1. +** Written by Matthew Conte +** http://tlsf.baisoku.org +** +** Based on the original documentation by Miguel Masmano: +** http://www.gii.upv.es/tlsf/main/docs +** +** This implementation was written to the specification +** of the document, therefore no GPL restrictions apply. +** +** Copyright (c) 2006-2016, Matthew Conte +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the copyright holder nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */ +/* pool_t: a block of memory that TLSF can manage. */ +typedef void* tlsf_t; +typedef void* pool_t; + +/* Create/destroy a memory pool. */ +tlsf_t tlsf_create(void* mem); +tlsf_t tlsf_create_with_pool(void* mem, size_t bytes); +void tlsf_destroy(tlsf_t tlsf); +pool_t tlsf_get_pool(tlsf_t tlsf); + +/* Add/remove memory pools. */ +pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes); +void tlsf_remove_pool(tlsf_t tlsf, pool_t pool); + +/* malloc/memalign/realloc/free replacements. */ +void* tlsf_malloc(tlsf_t tlsf, size_t bytes); +void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes); +void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size); +void tlsf_free(tlsf_t tlsf, void* ptr); + +/* Returns internal block size, not original request size */ +size_t tlsf_block_size(void* ptr); + +/* Overheads/limits of internal structures. */ +size_t tlsf_size(void); +size_t tlsf_align_size(void); +size_t tlsf_block_size_min(void); +size_t tlsf_block_size_max(void); +size_t tlsf_pool_overhead(void); +size_t tlsf_alloc_overhead(void); + +/* Debugging. */ +typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user); +void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user); +/* Returns nonzero if any internal consistency check fails. */ +int tlsf_check(tlsf_t tlsf); +int tlsf_check_pool(pool_t pool); + +#if defined(__cplusplus) +}; +#endif + +#endif diff --git a/User/system/sgl/sgl.h b/User/system/sgl/sgl.h new file mode 100644 index 0000000..b6a3961 --- /dev/null +++ b/User/system/sgl/sgl.h @@ -0,0 +1,65 @@ +/* source/sgl.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_H__ +#define __SGL_H__ + +#include +#include +#include +#include +#include +#include +#include "widgets/line/sgl_line.h" +#include "widgets/rectangle/sgl_rectangle.h" +#include "widgets/circle/sgl_circle.h" +#include "widgets/ring/sgl_ring.h" +#include "widgets/arc/sgl_arc.h" +#include "widgets/button/sgl_button.h" +#include "widgets/slider/sgl_slider.h" +#include "widgets/progress/sgl_progress.h" +#include "widgets/label/sgl_label.h" +#include "widgets/switch/sgl_switch.h" +#include "widgets/msgbox/sgl_msgbox.h" +#include "widgets/textline/sgl_textline.h" +#include "widgets/textbox/sgl_textbox.h" +#include "widgets/checkbox/sgl_checkbox.h" +#include "widgets/icon/sgl_icon.h" +// #include "widgets/listview/sgl_listview.h" +#include "widgets/numberkbd/sgl_numberkbd.h" +#include "widgets/keyboard/sgl_keyboard.h" +#include "widgets/unzip_image/sgl_unzip_image.h" +#include "widgets/led/sgl_led.h" +#include "widgets/2dball/sgl_2dball.h" +#include "widgets/scroll/sgl_scroll.h" +#include "widgets/dropdown/sgl_dropdown.h" +#include "widgets/scope/sgl_scope.h" +#include "widgets/ext_img/sgl_ext_img.h" +#include "widgets/polygon/sgl_polygon.h" +#include "widgets/box/sgl_box.h" +#include "widgets/canvas/sgl_canvas.h" +#include "widgets/bar/sgl_bar.h" +#include "widgets/win/sgl_win.h" + +#endif // __SGL_H__ diff --git a/User/system/sgl/sgl_config.h b/User/system/sgl/sgl_config.h new file mode 100644 index 0000000..b281e21 --- /dev/null +++ b/User/system/sgl/sgl_config.h @@ -0,0 +1,23 @@ +//**************************************************************** +//* lite-manager * +//* NOTE: do not edit this file as it is automatically generated * +//**************************************************************** + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + + +#define CONFIG_SGL_PANEL_PIXEL_DEPTH 16 +#define CONFIG_SGL_EVENT_QUEUE_SIZE 16 +#define CONFIG_SGL_ANIMATION 1 +#define CONFIG_SGL_ANIMATION_TICK_MS 10 +#define CONFIG_SGL_DEBUG 1 +#define CONFIG_SGL_LOG_COLOR 1 +#define CONFIG_SGL_LOG_LEVEL 0 +#define CONFIG_SGL_BOOT_LOGO 1 +#define CONFIG_SGL_HEAP_ALGO lwmem +#define CONFIG_SGL_HEAP_MEMORY_SIZE 10240 +#define CONFIG_SGL_FONT_SONG23 1 + + +#endif //!__CONFIG_H__ diff --git a/User/system/sgl/widgets/2dball/sgl_2dball.c b/User/system/sgl/widgets/2dball/sgl_2dball.c new file mode 100644 index 0000000..6c91d8f --- /dev/null +++ b/User/system/sgl/widgets/2dball/sgl_2dball.c @@ -0,0 +1,122 @@ +/* source/widgets/sgl_2dball.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_2dball.h" + + +static void sgl_2dball_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj); + int16_t cx = 0, cy = 0; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_area_t clip; + sgl_color_t *buf = NULL, *blend = NULL; + + cx = (ball->obj.coords.x1 + ball->obj.coords.x2) / 2; + cy = (ball->obj.coords.y1 + ball->obj.coords.y2) / 2; + + if (!sgl_surf_clip(surf, &obj->area, &clip)) { + return; + } + + sgl_area_t c_rect = { + .x1 = cx - obj->radius, + .x2 = cx + obj->radius, + .y1 = cy - obj->radius, + .y2 = cy + obj->radius + }; + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + int y2 = 0, real_r2 = 0, edge_alpha = 0; + int r2 = sgl_pow2(obj->radius); + int r2_edge = sgl_pow2(obj->radius + 1); + int ds_alpha = SGL_ALPHA_MIN; + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + y2 = sgl_pow2(y - cy); + blend = buf; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + ds_alpha = real_r2 * SGL_ALPHA_NUM / r2; + + if (real_r2 >= r2_edge) { + if(x > cx) + break; + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + sgl_color_t color_mix = sgl_color_mixer(ball->bg_color, *blend, edge_alpha); + *blend = sgl_color_mixer(color_mix, *blend, ball->alpha); + } + else { + *blend = sgl_color_mixer(sgl_color_mixer(ball->bg_color, ball->color, ds_alpha), *blend, ball->alpha); + } + } + buf += surf->w; + } + } +} + + +/** + * @brief create a 2dball object + * @param parent parent of the 2dball + * @return 2dball object + */ +sgl_obj_t* sgl_2dball_create(sgl_obj_t* parent) +{ + sgl_2dball_t *ball = sgl_malloc(sizeof(sgl_2dball_t)); + if(ball == NULL) { + SGL_LOG_ERROR("sgl_2dball_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(ball, 0, sizeof(sgl_2dball_t)); + + sgl_obj_t *obj = &ball->obj; + sgl_obj_init(&ball->obj, parent); + obj->construct_fn = sgl_2dball_construct_cb; + obj->needinit = 1; + + ball->alpha = SGL_ALPHA_MAX; + ball->color = SGL_THEME_COLOR; + ball->bg_color = SGL_THEME_BG_COLOR; + + return obj; +} diff --git a/User/system/sgl/widgets/2dball/sgl_2dball.h b/User/system/sgl/widgets/2dball/sgl_2dball.h new file mode 100644 index 0000000..e41b647 --- /dev/null +++ b/User/system/sgl/widgets/2dball/sgl_2dball.h @@ -0,0 +1,110 @@ +/* source/widgets/sgl_2dball.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_2DBALL_H__ +#define __SGL_2DBALL_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl 2dball struct + * @obj: sgl general object + * @desc: pointer to 2dball draw descriptor + */ +typedef struct sgl_2dball { + sgl_obj_t obj; + uint8_t alpha; + sgl_color_t color; + sgl_color_t bg_color; + +}sgl_2dball_t; + + +/** + * @brief create a 2dball object + * @param parent parent of the 2dball + * @return 2dball object + */ +sgl_obj_t* sgl_2dball_create(sgl_obj_t* parent); + + +/** + * @brief set the color of the 2dball + * @param obj 2dball object + * @param color color + * @return none + */ +static inline void sgl_2dball_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj); + ball->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the background color of the 2dball + * @param obj 2dball object + * @param color background color + * @return none + */ +static inline void sgl_2dball_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj); + ball->bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the alpha of the 2dball + * @param obj 2dball object + * @param alpha alpha + * @return none + */ +static inline void sgl_2dball_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_2dball_t *ball = sgl_container_of(obj, sgl_2dball_t, obj); + ball->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the radius of the 2dball + * @param obj 2dball object + * @param radius radius + * @return none + */ +static inline void sgl_2dball_set_radius(sgl_obj_t *obj, uint16_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_2DBALL_H__ diff --git a/User/system/sgl/widgets/arc/sgl_arc.c b/User/system/sgl/widgets/arc/sgl_arc.c new file mode 100644 index 0000000..7dd76ef --- /dev/null +++ b/User/system/sgl/widgets/arc/sgl_arc.c @@ -0,0 +1,119 @@ +/* source/widgets/sgl_arc.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_arc.h" + + +static void sgl_arc_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + int16_t tb_angle = 0; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + arc->desc.cx = (obj->coords.x2 + obj->coords.x1) / 2; + arc->desc.cy = (obj->coords.y2 + obj->coords.y1) / 2; + + if(arc->desc.start_angle == 0 && arc->desc.end_angle == 360) { + sgl_draw_fill_ring(surf, &arc->obj.area, arc->desc.cx, arc->desc.cy, arc->desc.radius_in, arc->desc.radius_out, arc->desc.color, arc->desc.alpha); + } + else { + sgl_draw_fill_arc(surf, &arc->obj.area, &arc->desc); + } + } + else if(evt->type == SGL_EVENT_PRESSED || + evt->type == SGL_EVENT_MOVE_DOWN || evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT + ) { + tb_angle = sgl_atan2_angle(evt->pos.x - arc->desc.cx, evt->pos.y - arc->desc.cy); + tb_angle = 360 - tb_angle; + if ((tb_angle != arc->desc.end_angle) && tb_angle >= 0 && tb_angle <= 360) { + arc->desc.end_angle = tb_angle; + } + + if(obj->event_fn) { + obj->event_fn(evt); + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + if(obj->event_fn) { + obj->event_fn(evt); + } + } + else if(SGL_EVENT_DRAW_INIT) { + if(arc->desc.radius_out < 0) { + arc->desc.radius_out = (obj->coords.x2 - obj->coords.x1) / 2; + } + + if(arc->desc.radius_in < 0) { + arc->desc.radius_in = arc->desc.radius_out - 2; + } + } +} + + +/** + * @brief create an arc object + * @param parent parent object + * @return arc object + */ +sgl_obj_t* sgl_arc_create(sgl_obj_t* parent) +{ + sgl_arc_t *arc = sgl_malloc(sizeof(sgl_arc_t)); + if(arc == NULL) { + SGL_LOG_ERROR("sgl_arc_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(arc, 0, sizeof(sgl_arc_t)); + + sgl_obj_t *obj = &arc->obj; + sgl_obj_init(&arc->obj, parent); + obj->needinit = 1; + obj->clickable = 1; + obj->movable = 1; + + arc->desc.alpha = SGL_THEME_ALPHA; + arc->desc.mode = SGL_ARC_MODE_NORMAL; + arc->desc.color = SGL_THEME_BG_COLOR; + arc->desc.bg_color = SGL_THEME_COLOR; + arc->desc.start_angle = 0; + arc->desc.end_angle = 360; + arc->desc.radius_out = -1; + arc->desc.radius_in = -1; + arc->desc.cx = -1; + arc->desc.cy = -1; + + obj->construct_fn = sgl_arc_construct_cb; + + return obj; +} diff --git a/User/system/sgl/widgets/arc/sgl_arc.h b/User/system/sgl/widgets/arc/sgl_arc.h new file mode 100644 index 0000000..abdf233 --- /dev/null +++ b/User/system/sgl/widgets/arc/sgl_arc.h @@ -0,0 +1,149 @@ +/* source/widgets/sgl_arc.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef __SGL_ARC_H__ +#define __SGL_ARC_H__ + + +typedef struct sgl_arc { + sgl_obj_t obj; + sgl_draw_arc_t desc; + int16_t width; +}sgl_arc_t; + + +/** + * @brief create an arc object + * @param parent parent object + * @return arc object + */ +sgl_obj_t* sgl_arc_create(sgl_obj_t* parent); + + +/** + * @brief set arc object color + * @param obj arc object + * @param color arc color + * @return none + */ +static inline void sgl_arc_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object background color + * @param obj arc object + * @param color arc background color + * @return none + */ +static inline void sgl_arc_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object alpha + * @param obj arc object + * @param alpha arc alpha + * @return none + */ +static inline void sgl_arc_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object radius + * @param obj arc object + * @param radius_in arc radius_in + * @param radius_out arc radius_out + * @return none + */ +static inline void sgl_arc_set_radius(sgl_obj_t *obj, int16_t radius_in, int16_t radius_out) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + sgl_obj_set_radius(obj, radius_out); + arc->desc.radius_in = radius_in; + arc->desc.radius_out = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object mode + * @param obj arc object + * @param mode arc mode + * @return none + */ +static inline void sgl_arc_set_mode(sgl_obj_t *obj, uint8_t mode) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.mode = mode; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object start angle + * @param obj arc object + * @param angle arc start angle + * @return none + * @note angle should be in range [0, 360] + */ +static inline void sgl_arc_set_start_angle(sgl_obj_t *obj, int16_t angle) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.start_angle = angle; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set arc object end angle + * @param obj arc object + * @param angle arc end angle + * @return none + * @note angle should be in range [0, 360] + */ +static inline void sgl_arc_set_end_angle(sgl_obj_t *obj, int16_t angle) +{ + sgl_arc_t *arc = sgl_container_of(obj, sgl_arc_t, obj); + arc->desc.end_angle = angle; + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_ARC_H__ diff --git a/User/system/sgl/widgets/bar/sgl_bar.c b/User/system/sgl/widgets/bar/sgl_bar.c new file mode 100644 index 0000000..65f272e --- /dev/null +++ b/User/system/sgl/widgets/bar/sgl_bar.c @@ -0,0 +1,123 @@ +/* source/widgets/sgl_bar.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_bar.h" + + +static void sgl_bar_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + + sgl_draw_rect_t desc = { + .alpha = bar->alpha, + .border = obj->border, + .border_color = bar->border_color, + .pixmap = bar->pixmap, + .color = bar->track_color, + .radius = obj->radius, + }; + + sgl_area_t knob = { + .x1 = obj->coords.x1 + obj->border, + .x2 = obj->coords.x2 - obj->border, + .y1 = obj->coords.y1 + obj->border, + .y2 = obj->coords.y2 - obj->border, + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if(bar->direct == SGL_DIRECT_HORIZONTAL) { + knob.x2 = obj->coords.x1 + (obj->coords.x2 - obj->coords.x1) * bar->value / 100 - obj->border; + } + else { + knob.y1 = obj->coords.y2 - (obj->coords.y2 - obj->coords.y1) * bar->value / 100 + obj->border; + } + + /* set knob area */ + sgl_area_selfclip(&knob, &obj->area); + + sgl_draw_rect(surf, &obj->area, &obj->coords, &desc); + sgl_draw_fill_rect_with_border(surf, &knob, &obj->coords, obj->radius, bar->fill_color, bar->border_color, obj->border, bar->alpha); + } + else if(evt->type == SGL_EVENT_PRESSED || + evt->type == SGL_EVENT_MOVE_DOWN || evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT + ) { + if(bar->direct == SGL_DIRECT_HORIZONTAL) { + bar->value = (evt->pos.x - obj->coords.x1) * 100 / (obj->coords.x2 - obj->coords.x1); + } + else { + bar->value = (obj->coords.y2 - evt->pos.y) * 100 / (obj->coords.y2 - obj->coords.y1); + } + + if(evt->type == SGL_EVENT_PRESSED) { + sgl_obj_size_zoom(obj, 2); + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + sgl_obj_size_zoom(obj, -2); + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a bar object + * @param parent parent object of the bar + * @return bar object + */ +sgl_obj_t* sgl_bar_create(sgl_obj_t* parent) +{ + sgl_bar_t *bar = sgl_malloc(sizeof(sgl_bar_t)); + if(bar == NULL) { + SGL_LOG_ERROR("sgl_bar_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(bar, 0, sizeof(sgl_bar_t)); + + sgl_obj_t *obj = &bar->obj; + sgl_obj_init(&bar->obj, parent); + sgl_obj_set_clickable(obj); + sgl_obj_set_movable(obj); + obj->construct_fn = sgl_bar_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + bar->direct = SGL_DIRECT_HORIZONTAL; + bar->alpha = SGL_THEME_ALPHA; + bar->track_color = SGL_THEME_COLOR; + bar->border_color = SGL_THEME_BORDER_COLOR; + bar->fill_color = SGL_THEME_BG_COLOR; + bar->alpha = SGL_THEME_ALPHA; + + return obj; +} diff --git a/User/system/sgl/widgets/bar/sgl_bar.h b/User/system/sgl/widgets/bar/sgl_bar.h new file mode 100644 index 0000000..74d98c9 --- /dev/null +++ b/User/system/sgl/widgets/bar/sgl_bar.h @@ -0,0 +1,204 @@ +/* source/widgets/sgl_bar.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_BAR_H__ +#define __SGL_BAR_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl bar struct + * @obj: sgl general object + * @param track_color track color + * @param border_color border color + * @param pixmap pixmap + * @param fill_color fill color + * @param direct bar direction + * @param value bar value + * @param alpha alpha + */ +typedef struct sgl_bar { + sgl_obj_t obj; + sgl_color_t track_color; + sgl_color_t border_color; + const sgl_pixmap_t *pixmap; + sgl_color_t fill_color; + /* 0: horizontal, 1: vertical */ + uint8_t direct : 1; + uint8_t value : 7; + uint8_t alpha; +} sgl_bar_t; + +/** + * @brief create a bar object + * @param parent parent object of the bar + * @return bar object + */ +sgl_obj_t* sgl_bar_create(sgl_obj_t* parent); + +/** + * @brief set the fill color of the bar + * @param obj bar object + * @param color fill color + * @return none + */ +static inline void sgl_bar_set_fill_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->fill_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the fill alpha of the bar + * @param obj bar object + * @param alpha fill alpha + * @return none + */ +static inline void sgl_bar_set_fill_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the track color of the bar + * @param obj bar object + * @param color track color + * @return none + */ +static inline void sgl_bar_set_track_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->track_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the track alpha of the bar + * @param obj bar object + * @param alpha track alpha + * @return none + */ +static inline void sgl_bar_set_track_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the bar direction + * @param obj bar object + * @param direct bar direction + * @return none + * @note direct : SGL_DIRECT_HORIZONTAL or SGL_DIRECT_VERTICAL + */ +static inline void sgl_bar_set_direct(sgl_obj_t *obj, uint8_t direct) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->direct = direct; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the bar radius + * @param obj bar object + * @param radius bar radius + * @return none + */ +static inline void sgl_bar_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the bar value + * @param obj bar object + * @param value bar value + * @return none + */ +static inline void sgl_bar_set_value(sgl_obj_t *obj, uint8_t value) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->value = value; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get the bar value + * @param obj bar object + * @return bar value + */ +static inline uint8_t sgl_bar_get_value(sgl_obj_t *obj) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + return bar->value; +} + +/** + * @brief set the bar border width + * @param obj bar object + * @param width border width + */ +static inline void sgl_bar_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the bar border color + * @param obj bar object + * @param color border color + */ +static inline void sgl_bar_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the bar pixmap + * @param obj bar object + * @param pixmap pixmap + */ +static inline void sgl_bar_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_bar_t *bar = sgl_container_of(obj, sgl_bar_t, obj); + bar->pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_BAR_H__ diff --git a/User/system/sgl/widgets/box/sgl_box.c b/User/system/sgl/widgets/box/sgl_box.c new file mode 100644 index 0000000..da2dbb8 --- /dev/null +++ b/User/system/sgl/widgets/box/sgl_box.c @@ -0,0 +1,265 @@ +/* source/widgets/sgl_box.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sgl_box.h" + + +#define SGL_BOX_SCROLL_WIDTH (4) + +static void sgl_box_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + int16_t height = obj->coords.y2 - obj->coords.y1 - 2 * box->bg.radius; + int16_t width = obj->coords.x2 - obj->coords.x1 - 2 * box->bg.radius; + int16_t scroll_height = sgl_max(height / 8, SGL_BOX_SCROLL_WIDTH); + int16_t scroll_width = sgl_max(width / 8, SGL_BOX_SCROLL_WIDTH); + sgl_rect_t area; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + area.x1 = obj->coords.x1 + box->bg.radius; + area.y1 = obj->coords.y1 + box->bg.radius; + area.x2 = obj->coords.x2 - box->bg.radius; + area.y2 = obj->coords.y2 - box->bg.radius; + + sgl_draw_rect(surf, &obj->area, &obj->coords, &box->bg); + + // Draw scrollbars if enabled + if(box->scroll_enable) { + // Draw vertical scrollbar if vertical scrolling is enabled and showing is enabled + if (((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) + && box->show_v_scrollbar) { + area.x1 = obj->coords.x2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius; + area.y1 = obj->coords.y1 + box->bg.radius; + area.x2 = obj->coords.x2 - box->bg.radius; + + // Calculate scroll bar position based on content size and current offset + // Use elastic_scroll values to determine content size for proper scrollbar positioning + int16_t content_height = height + (box->elastic_scroll_up + box->elastic_scroll_down); + + if(content_height > height && content_height > 0) { + // Calculate the scroll bar's position based on the current y_offset + float scroll_ratio = (float)(-box->y_offset) / (content_height - height); + scroll_ratio = sgl_clamp(scroll_ratio, 0.0f, 1.0f); // Clamp between 0 and 1 + + int16_t max_scroll_pos = height - scroll_height; + area.y1 = obj->coords.y1 + box->bg.radius + (int16_t)(max_scroll_pos * scroll_ratio); + area.y2 = area.y1 + scroll_height; + } else { + // If content fits, position scrollbar at the top + area.y1 = obj->coords.y1 + box->bg.radius; + area.y2 = area.y1 + scroll_height; + } + + sgl_draw_fill_rect(surf, &obj->area, &area, SGL_BOX_SCROLL_WIDTH / 2, box->scroll_color, 128); + } + + // Draw horizontal scrollbar if horizontal scrolling is enabled and showing is enabled + if (((box->scroll_mode & SGL_BOX_SCROLL_HORIZONTAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) + && box->show_h_scrollbar) { + // Position horizontal scrollbar near the bottom-left, closer to vertical scrollbar + area.x1 = obj->coords.x1 + box->bg.radius; + area.y1 = obj->coords.y2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius; + area.y2 = obj->coords.y2 - box->bg.radius; + + // Adjust the right edge to not overlap with vertical scrollbar if both are visible + if ((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) { + area.x2 = obj->coords.x2 - SGL_BOX_SCROLL_WIDTH - box->bg.radius; + } else { + area.x2 = obj->coords.x2 - box->bg.radius; + } + + // Calculate scroll bar position based on content size and current offset + int16_t content_width = width + (box->elastic_scroll_left + box->elastic_scroll_right); + + if(content_width > width && content_width > 0) { + // Calculate the scroll bar's position based on the current x_offset + float scroll_ratio = (float)(-box->x_offset) / (content_width - width); + scroll_ratio = sgl_clamp(scroll_ratio, 0.0f, 1.0f); // Clamp between 0 and 1 + + int16_t max_scroll_pos = (area.x2 - area.x1) - scroll_width; + area.x1 = area.x1 + (int16_t)(max_scroll_pos * scroll_ratio); + area.x2 = area.x1 + scroll_width; + } else { + // If content fits, position scrollbar at the left + area.x1 = obj->coords.x1 + box->bg.radius; + area.x2 = area.x1 + scroll_width; + } + + sgl_draw_fill_rect(surf, &obj->area, &area, SGL_BOX_SCROLL_WIDTH / 2, box->scroll_color, 128); + } + } + } + else if(evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_DOWN) { + // Check if vertical scrolling is enabled + if((box->scroll_mode & SGL_BOX_SCROLL_VERTICAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) { + // Update text offset - determine scroll direction based on event type + int16_t distance = evt->type == SGL_EVENT_MOVE_UP ? -evt->distance : evt->distance; + int16_t new_offset = box->y_offset + distance; + + // Calculate limits based on elastic_scroll values + int16_t min_elastic, max_elastic; + // Calculate content dimensions based on elastic_scroll values + int16_t content_height = height + (box->elastic_scroll_up + box->elastic_scroll_down); + // Determine maximum scroll distance + int16_t max_scroll_distance = content_height - height; + + if(box->elastic_scroll_up > 0 || box->elastic_scroll_down > 0) { + // If elastic scrolling is enabled (any direction limit > 0), limit to boundary plus elastic offset + // Apply actual elastic limits + min_elastic = -max_scroll_distance - box->elastic_scroll_down; // Allow scrolling down with elastic limit + max_elastic = box->elastic_scroll_up; // Allow scrolling up with elastic limit + } else { + // If elastic scrolling is disabled (both values are 0), limit to content boundaries + min_elastic = -max_scroll_distance; // max scroll down + max_elastic = 0; // max scroll up + } + + int16_t constrained_new_offset = sgl_clamp(new_offset, min_elastic, max_elastic); + int16_t offset_delta = constrained_new_offset - box->y_offset; + + box->y_offset = constrained_new_offset; + + // Move all children vertically + sgl_obj_move_child_pos_y(obj, offset_delta); + sgl_obj_set_dirty(obj); + } + } + else if(evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT) { + // Check if horizontal scrolling is enabled + if((box->scroll_mode & SGL_BOX_SCROLL_HORIZONTAL_ONLY) || (box->scroll_mode & SGL_BOX_SCROLL_BOTH)) { + // Update text offset - determine scroll direction based on event type + int16_t distance = evt->type == SGL_EVENT_MOVE_LEFT ? -evt->distance : evt->distance; + int16_t new_offset = box->x_offset + distance; + + // Calculate limits based on elastic_scroll values + int16_t min_elastic, max_elastic; + // Calculate content dimensions based on elastic_scroll values + int16_t content_width = width + (box->elastic_scroll_left + box->elastic_scroll_right); + // Determine maximum scroll distance + int16_t max_scroll_distance = content_width - width; + + if(box->elastic_scroll_left > 0 || box->elastic_scroll_right > 0) { + // If elastic scrolling is enabled (any direction limit > 0), limit to boundary plus elastic offset + // Apply actual elastic limits + min_elastic = -max_scroll_distance - box->elastic_scroll_right; // Allow scrolling right with elastic limit + max_elastic = box->elastic_scroll_left; // Allow scrolling left with elastic limit + } else { + // If elastic scrolling is disabled (both values are 0), limit to content boundaries + min_elastic = -max_scroll_distance; // max scroll right + max_elastic = 0; // max scroll left + } + + int16_t constrained_new_offset = sgl_clamp(new_offset, min_elastic, max_elastic); + int16_t offset_delta = constrained_new_offset - box->x_offset; + + box->x_offset = constrained_new_offset; + + // Move all children horizontally + sgl_obj_move_child_pos_x(obj, offset_delta); + sgl_obj_set_dirty(obj); + } + } + else if (evt->type == SGL_EVENT_PRESSED) { + box->scroll_enable = 1; + sgl_obj_set_dirty(obj); + } + else if (evt->type == SGL_EVENT_RELEASED) { + box->scroll_enable = 0; + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a box object + * @param parent parent of the box + * @return pointer to the box object + */ +sgl_obj_t* sgl_box_create(sgl_obj_t* parent) +{ + sgl_box_t *box = sgl_malloc(sizeof(sgl_box_t)); + if(box == NULL) { + SGL_LOG_ERROR("sgl_box_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(box, 0, sizeof(sgl_box_t)); + + sgl_obj_t *obj = &box->obj; + sgl_obj_init(&box->obj, parent); + obj->construct_fn = sgl_box_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + obj->focus = 1; + + sgl_obj_set_clickable(obj); + sgl_obj_set_movable(obj); + + box->bg.alpha = SGL_THEME_ALPHA; + box->bg.color = SGL_THEME_COLOR; + box->bg.radius = 10; + box->bg.border = 1; + sgl_obj_set_border_width(obj, 1); + box->bg.border_color = SGL_THEME_BORDER_COLOR; + box->scroll_color = SGL_THEME_SCROLL_FG_COLOR; + + box->x_offset = 0; + box->y_offset = 0; + box->scroll_enable = 0; + box->show_v_scrollbar = 1; + box->show_h_scrollbar = 1; + box->scroll_mode = SGL_BOX_SCROLL_BOTH; + box->elastic_scroll_up = 0; // Default: unlimited scrolling up + box->elastic_scroll_down = 0; // Default: unlimited scrolling down + box->elastic_scroll_left = 0; // Default: unlimited scrolling left + box->elastic_scroll_right = 0; // Default: unlimited scrolling right + + return obj; +} + +/** + * @brief Set the elastic scroll limits for up and down directions + * @param obj box object + * @param up_limit maximum pixels allowed when scrolling up (0 for unlimited) + * @param down_limit maximum pixels allowed when scrolling down (0 for unlimited) + * @param left_limit maximum pixels allowed when scrolling left (0 for unlimited) + * @param right_limit maximum pixels allowed when scrolling right (0 for unlimited) + * @return none + */ +void sgl_box_set_elastic_scroll(sgl_obj_t* obj, int16_t up_limit, int16_t down_limit, int16_t left_limit, int16_t right_limit) +{ + SGL_ASSERT(obj != NULL); + sgl_box_t *box = (sgl_box_t*)obj; + box->elastic_scroll_up = up_limit; + box->elastic_scroll_down = down_limit; + box->elastic_scroll_left = left_limit; + box->elastic_scroll_right = right_limit; +} diff --git a/User/system/sgl/widgets/box/sgl_box.h b/User/system/sgl/widgets/box/sgl_box.h new file mode 100644 index 0000000..7a18043 --- /dev/null +++ b/User/system/sgl/widgets/box/sgl_box.h @@ -0,0 +1,189 @@ +/* source/widgets/sgl_box.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_BOX_H__ +#define __SGL_BOX_H__ + +#include +#include +#include +#include +#include +#include +#include + +// Define scroll modes +#define SGL_BOX_SCROLL_VERTICAL_ONLY (0x01) // Vertical scrolling only +#define SGL_BOX_SCROLL_HORIZONTAL_ONLY (0x02) // Horizontal scrolling only +#define SGL_BOX_SCROLL_BOTH (0x03) // Both vertical and horizontal scrolling enabled + +/** + * @brief sgl box struct + * @desc: Container for scrolling child widgets + */ +typedef struct sgl_box { + sgl_obj_t obj; + sgl_draw_rect_t bg; + int16_t x_offset; // X-axis offset + int16_t y_offset; // Y-axis offset + sgl_color_t scroll_color; // scroll color; + uint8_t scroll_mode; // Scroll mode (vertical/horizontal/both) + uint8_t scroll_enable : 1; // Whether scrolling is enabled + uint8_t show_v_scrollbar : 1; // Whether to show the vertical scrollbar + uint8_t show_h_scrollbar : 1; // Whether to show the horizontal scrollbar + int16_t elastic_scroll_up; // Maximum allowable upward elastic scroll offset + int16_t elastic_scroll_down; // Maximum allowable downward elastic scroll offset + int16_t elastic_scroll_left; // Maximum allowable leftward elastic scroll offset + int16_t elastic_scroll_right; // Maximum allowable rightward elastic scroll offset +} sgl_box_t; + + +/** + * @brief create a box object + * @param parent parent of the box + * @return box object + */ +sgl_obj_t* sgl_box_create(sgl_obj_t* parent); + + +/** + * @brief set background color of the box + * @param obj box object + * @param color background color to be set + * @return none + */ +static inline void sgl_box_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->bg.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set radius of the box + * @param obj box object + * @param radius radius to be set + * @return none + */ +static inline void sgl_box_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + sgl_obj_set_radius(obj, radius); + box->bg.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set border color of the box + * @param obj box object + * @param color border color to be set + * @return none + */ +static inline void sgl_box_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->bg.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set border width of the box + * @param obj box object + * @param width border width to be set + * @return none + */ +static inline void sgl_box_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->bg.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set box pixmap + * @param obj box object + * @param pixmap pixmap to be set + * @return none + */ +static inline void sgl_box_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->bg.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set the elastic scroll limits for up and down directions + * @param obj box object + * @param up_limit maximum pixels allowed when scrolling up (0 for unlimited) + * @param down_limit maximum pixels allowed when scrolling down (0 for unlimited) + * @param left_limit maximum pixels allowed when scrolling left (0 for unlimited) + * @param right_limit maximum pixels allowed when scrolling right (0 for unlimited) + * @return none + */ +void sgl_box_set_elastic_scroll(sgl_obj_t* obj, int16_t up_limit, int16_t down_limit, int16_t left_limit, int16_t right_limit); + +/** + * @brief set scrollbar color of the box + * @param obj box object + * @param color scrollbar color to be set + * @return none + */ +static inline void sgl_box_set_scrollbar_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->scroll_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set whether to show scrollbars + * @param obj box object + * @param show_vertical whether to show vertical scrollbar (1 to show, 0 to hide) + * @param show_horizontal whether to show horizontal scrollbar (1 to show, 0 to hide) + * @return none + */ +static inline void sgl_box_set_show_scrollbar(sgl_obj_t *obj, uint8_t show_vertical, uint8_t show_horizontal) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->show_v_scrollbar = show_vertical; + box->show_h_scrollbar = show_horizontal; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set alpha (transparency) of the box + * @param obj box object + * @param alpha alpha value to be set (0-255, where 0 is fully transparent and 255 is fully opaque) + * @return none + */ +static inline void sgl_box_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_box_t *box = sgl_container_of(obj, sgl_box_t, obj); + box->bg.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_BOX_H__ diff --git a/User/system/sgl/widgets/build.cmake b/User/system/sgl/widgets/build.cmake new file mode 100644 index 0000000..2ddb1ef --- /dev/null +++ b/User/system/sgl/widgets/build.cmake @@ -0,0 +1,54 @@ +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +set(SGL_SOURCE + ${SGL_SOURCE} + ${CMAKE_CURRENT_LIST_DIR}/line/sgl_line.c + ${CMAKE_CURRENT_LIST_DIR}/rectangle/sgl_rectangle.c + ${CMAKE_CURRENT_LIST_DIR}/circle/sgl_circle.c + ${CMAKE_CURRENT_LIST_DIR}/ring/sgl_ring.c + ${CMAKE_CURRENT_LIST_DIR}/arc/sgl_arc.c + ${CMAKE_CURRENT_LIST_DIR}/button/sgl_button.c + ${CMAKE_CURRENT_LIST_DIR}/slider/sgl_slider.c + ${CMAKE_CURRENT_LIST_DIR}/progress/sgl_progress.c + ${CMAKE_CURRENT_LIST_DIR}/label/sgl_label.c + ${CMAKE_CURRENT_LIST_DIR}/switch/sgl_switch.c + ${CMAKE_CURRENT_LIST_DIR}/msgbox/sgl_msgbox.c + ${CMAKE_CURRENT_LIST_DIR}/textline/sgl_textline.c + ${CMAKE_CURRENT_LIST_DIR}/textbox/sgl_textbox.c + ${CMAKE_CURRENT_LIST_DIR}/checkbox/sgl_checkbox.c + ${CMAKE_CURRENT_LIST_DIR}/icon/sgl_icon.c + ${CMAKE_CURRENT_LIST_DIR}/numberkbd/sgl_numberkbd.c + ${CMAKE_CURRENT_LIST_DIR}/keyboard/sgl_keyboard.c + ${CMAKE_CURRENT_LIST_DIR}/led/sgl_led.c + ${CMAKE_CURRENT_LIST_DIR}/2dball/sgl_2dball.c + ${CMAKE_CURRENT_LIST_DIR}/unzip_image/sgl_unzip_image.c + ${CMAKE_CURRENT_LIST_DIR}/scroll/sgl_scroll.c + ${CMAKE_CURRENT_LIST_DIR}/dropdown/sgl_dropdown.c + ${CMAKE_CURRENT_LIST_DIR}/scope/sgl_scope.c + ${CMAKE_CURRENT_LIST_DIR}/polygon/sgl_polygon.c + ${CMAKE_CURRENT_LIST_DIR}/box/sgl_box.c + ${CMAKE_CURRENT_LIST_DIR}/canvas/sgl_canvas.c + ${CMAKE_CURRENT_LIST_DIR}/bar/sgl_bar.c + ${CMAKE_CURRENT_LIST_DIR}/win/sgl_win.c +) diff --git a/User/system/sgl/widgets/button/sgl_button.c b/User/system/sgl/widgets/button/sgl_button.c new file mode 100644 index 0000000..57c6436 --- /dev/null +++ b/User/system/sgl/widgets/button/sgl_button.c @@ -0,0 +1,121 @@ +/* source/widgets/sgl_button.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_button.h" + + +/** + * @brief button construct callback + * @param surf: surface pointer + * @param obj: object pointer + * @param evt: event pointer + * @return none + * @note this function is called when the object is created or redraw + */ +static void sgl_button_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + sgl_pos_t align_pos; + sgl_rect_t fill_area; + sgl_draw_rect_t rect = { + .alpha = button->alpha, + .color = button->color, + .border = obj->border, + .border_color = button->border_color, + .pixmap = button->pixmap, + .radius = obj->radius, + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &obj->coords, &rect); + + if(button->text) { + SGL_ASSERT(button->font != NULL); + fill_area = sgl_obj_get_fill_rect(obj); + align_pos = sgl_get_text_pos(&fill_area, button->font, button->text, 0, (sgl_align_type_t)button->align); + + sgl_draw_string(surf, &obj->area, align_pos.x, align_pos.y, button->text, button->text_color, button->alpha, button->font); + } + } + else if(evt->type == SGL_EVENT_PRESSED) { + if(sgl_obj_is_flexible(obj)) { + sgl_obj_size_zoom(obj, 2); + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + if(sgl_obj_is_flexible(obj)) { + sgl_obj_size_zoom(obj, -2); + } + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a button object + * @param parent: parent object + * @return object pointer + * @note if parent is NULL, the button object will be created at the top level. + */ +sgl_obj_t* sgl_button_create(sgl_obj_t* parent) +{ + sgl_button_t *button = sgl_malloc(sizeof(sgl_button_t)); + if(button == NULL) { + SGL_LOG_ERROR("sgl_button_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(button, 0, sizeof(sgl_button_t)); + + sgl_obj_t *obj = &button->obj; + sgl_obj_init(&button->obj, parent); + sgl_obj_set_clickable(obj); + sgl_obj_set_flexible(obj); + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + sgl_obj_set_radius(obj, SGL_THEME_RADIUS); + + obj->construct_fn = sgl_button_construct_cb; + + button->alpha = SGL_THEME_ALPHA; + button->color = SGL_THEME_COLOR; + button->border_color = SGL_THEME_BORDER_COLOR; + button->pixmap = NULL; + + button->text = " "; + button->text_color = SGL_THEME_TEXT_COLOR; + button->font = sgl_get_system_font(); + button->align = SGL_ALIGN_CENTER; + + return obj; +} diff --git a/User/system/sgl/widgets/button/sgl_button.h b/User/system/sgl/widgets/button/sgl_button.h new file mode 100644 index 0000000..0d3bd12 --- /dev/null +++ b/User/system/sgl/widgets/button/sgl_button.h @@ -0,0 +1,193 @@ +/* source/widgets/sgl_button.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_BUTTON_H__ +#define __SGL_BUTTON_H__ + + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief Button object + * @obj: Button object + * @desc: Button object description + * @desc_text: Button object description text + */ +typedef struct sgl_button { + sgl_obj_t obj; + sgl_color_t color; + sgl_color_t border_color; + const sgl_pixmap_t *pixmap; + const char *text; + const sgl_font_t *font; + sgl_color_t text_color; + uint8_t alpha; + uint8_t align; +}sgl_button_t; + + +/** + * @brief create a button object + * @param parent: parent object + * @return object pointer + * @note if parent is NULL, the button object will be created at the top level. + */ +sgl_obj_t* sgl_button_create(sgl_obj_t* parent); + +/** + * @brief set button color + * @param obj: object pointer + * @param color: color + * @return none + */ +static inline void sgl_button_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button alpha + * @param obj: object pointer + * @param alpha: alpha + * @return none + */ +static inline void sgl_button_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button border width + * @param obj: object pointer + * @param width: border width + * @return none + */ +static inline void sgl_button_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button border color + * @param obj: object pointer + * @param color: border color + * @return none + */ +static inline void sgl_button_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button pixmap + * @param obj: object pointer + * @param pixmap: pixmap pointer + * @return none + */ +static inline void sgl_button_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button radius + * @param obj: object pointer + * @param radius: radius + * @return none + */ +static inline void sgl_button_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button text + * @param obj: object pointer + * @param text: text + * @return none + */ +static inline void sgl_button_set_text(sgl_obj_t *obj, const char *text) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button text color + * @param obj: object pointer + * @param color: text color + * @return none + */ +static inline void sgl_button_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button text align + * @param obj: object pointer + * @param align: align type + * @return none + */ +static inline void sgl_button_set_text_align(sgl_obj_t *obj, uint8_t align) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->align = align; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set button text font + * @param obj: object pointer + * @param font: font pointer + * @return none + */ +static inline void sgl_button_set_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_button_t *button = sgl_container_of(obj, sgl_button_t, obj); + button->font = font; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_BUTTON_H__ diff --git a/User/system/sgl/widgets/canvas/sgl_canvas.c b/User/system/sgl/widgets/canvas/sgl_canvas.c new file mode 100644 index 0000000..b75109f --- /dev/null +++ b/User/system/sgl/widgets/canvas/sgl_canvas.c @@ -0,0 +1,67 @@ +/* source/widgets/sgl_canvas.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_canvas.h" + + +static void sgl_canvas_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_canvas_t *canvas = sgl_container_of(obj, sgl_canvas_t, obj); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + SGL_ASSERT_INFO(canvas->painter != NULL, "you must set painter function"); + canvas->painter(surf, &obj->area, obj); + } +} + +/** + * @brief create a canvas object + * @param parent parent of the canvas + * @return canvas object + */ +sgl_obj_t* sgl_canvas_create(sgl_obj_t* parent) +{ + sgl_canvas_t *canvas = sgl_malloc(sizeof(sgl_canvas_t)); + if(canvas == NULL) { + SGL_LOG_ERROR("sgl_canvas_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(canvas, 0, sizeof(sgl_canvas_t)); + + sgl_obj_t *obj = &canvas->obj; + sgl_obj_init(&canvas->obj, parent); + obj->construct_fn = sgl_canvas_construct_cb; + + return obj; +} diff --git a/User/system/sgl/widgets/canvas/sgl_canvas.h b/User/system/sgl/widgets/canvas/sgl_canvas.h new file mode 100644 index 0000000..3a92f6c --- /dev/null +++ b/User/system/sgl/widgets/canvas/sgl_canvas.h @@ -0,0 +1,97 @@ +/* source/widgets/sgl_canvas.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_CANVAS_H__ +#define __SGL_CANVAS_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief For example, you can use the canvas widget: + * void painter_func(sgl_surf_t *surf, sgl_area_t *area, sgl_obj_t *obj) + * { + * for (int i = obj->coords.y1; i < obj->coords.y2; i += 10) { + * sgl_draw_fill_hline(surf, area, i, obj->coords.x1, obj->coords.x2, 5, SGL_COLOR_BLACK, 255); + * } + * } + * + * sgl_obj_t *canvas = sgl_canvas_create(NULL); + * sgl_obj_set_size(canvas, 800, 600); + * sgl_obj_set_pos_align(canvas, SGL_ALIGN_CENTER); + * sgl_canvas_set_painter_cb(canvas, painter_func); + */ + +typedef void (*sgl_painter_cb_t)(sgl_surf_t *surf, sgl_area_t *area, sgl_obj_t* obj); + +/** + * @brief sgl canvas struct + * @obj: sgl general object + * @painter: pointer to canvas painter function + * @priv: pointer to canvas private data + */ +typedef struct sgl_canvas { + sgl_obj_t obj; + sgl_painter_cb_t painter; + void *priv; +} sgl_canvas_t; + +/** + * @brief create a canvas object + * @param parent parent of the canvas + * @return canvas object + */ +sgl_obj_t* sgl_canvas_create(sgl_obj_t* parent); + +/** + * @brief set canvas painter + * @param obj canvas object + * @param painter painter function + */ +static inline void sgl_canvas_set_painter_cb(sgl_obj_t *obj, sgl_painter_cb_t painter) +{ + SGL_ASSERT(obj != NULL); + sgl_canvas_t *canvas = sgl_container_of(obj, sgl_canvas_t, obj); + canvas->painter = painter; +} + +/** + * @brief set canvas private data + * @param obj canvas object + * @param priv private data + * @param none + */ +static inline void sgl_canvas_set_private(sgl_obj_t *obj, void *priv) +{ + SGL_ASSERT(obj != NULL); + sgl_canvas_t *canvas = (sgl_canvas_t *)obj; + canvas->priv = priv; +} + +#endif // !__SGL_CANVAS_H__ diff --git a/User/system/sgl/widgets/checkbox/sgl_checkbox.c b/User/system/sgl/widgets/checkbox/sgl_checkbox.c new file mode 100644 index 0000000..4398e28 --- /dev/null +++ b/User/system/sgl/widgets/checkbox/sgl_checkbox.c @@ -0,0 +1,190 @@ +/* source/widgets/sgl_checkbox.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_checkbox.h" + + +static const uint8_t unchecked_pixmap[] = { + /* ï‚– */ + 0x00,0x03,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00, + 0x05,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xea,0x00,0x00,0x00, + 0x8e,0xfe,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xce,0xff,0xa0,0x00,0x00, + 0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xe0,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe0,0x00,0x00, + 0xef,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xcf,0xe0,0x00,0x00, + 0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x80,0x00,0x00, + 0x03,0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc5,0x00,0x00,0x00, +}; + + +static const uint8_t checked_pixmap[] = { + /* ï† */ + 0x00,0x03,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00, + 0x05,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x00,0x30,0x00, + 0x8e,0xfe,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x80,0x5e,0xfa,0x00, + 0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xef,0xff,0xa0, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xff,0xff,0xe0, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xef,0xff,0xff,0xe0, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x5e,0xff,0xff,0xfe,0x30, + 0xee,0x50,0x03,0x55,0x00,0x00,0x00,0x05,0xef,0xff,0xff,0xe3,0x00, + 0xee,0x50,0x3e,0xfe,0x80,0x00,0x00,0x5e,0xff,0xff,0xfe,0x30,0x00, + 0xee,0x50,0xef,0xff,0xe8,0x00,0x05,0xef,0xff,0xff,0xe3,0x00,0x00, + 0xee,0x58,0xef,0xff,0xfe,0x80,0x5e,0xff,0xff,0xfe,0x30,0x00,0x00, + 0xee,0x50,0xcf,0xff,0xff,0xe8,0xef,0xff,0xff,0xe3,0x00,0x00,0x00, + 0xee,0x50,0x0c,0xff,0xff,0xff,0xff,0xff,0xfe,0x30,0x85,0x00,0x00, + 0xee,0x50,0x00,0xcf,0xff,0xff,0xff,0xff,0xe3,0x0c,0xe8,0x00,0x00, + 0xee,0x50,0x00,0x0c,0xff,0xff,0xff,0xfe,0x30,0x0e,0xe8,0x00,0x00, + 0xee,0x50,0x00,0x00,0xcf,0xff,0xff,0xe3,0x00,0x0e,0xe8,0x00,0x00, + 0xee,0x50,0x00,0x00,0x0c,0xff,0xfe,0x30,0x00,0x0e,0xe8,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0xcf,0xe3,0x00,0x00,0x0e,0xe8,0x00,0x00, + 0xee,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0xe8,0x00,0x00, + 0xef,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xcf,0xe3,0x00,0x00, + 0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x80,0x00,0x00, + 0x03,0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc5,0x00,0x00,0x00, +}; + + +static sgl_icon_pixmap_t unchecked_icon = { + .bitmap = unchecked_pixmap, + .height = 22, + .width = 26, +}; + + +static sgl_icon_pixmap_t checked_icon = { + .bitmap = checked_pixmap, + .height = 22, + .width = 26, +}; + + +/** + * @brief checkbox construct callback + * @param surf surface pointer + * @param obj checkbox object + * @param evt event parameter + * @return none + */ +static void sgl_checkbox_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + int text_x = 0, icon_y = 0; + sgl_pos_t align_pos; + + SGL_ASSERT(checkbox->font != NULL); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if(checkbox->status) { + checkbox->icon = &checked_icon; + } + else { + checkbox->icon = &unchecked_icon; + } + + if (checkbox->icon) { + text_x = checkbox->icon->width + 2; + } + + align_pos = sgl_get_text_pos(&obj->coords, checkbox->font, checkbox->text, text_x, SGL_ALIGN_CENTER); + + if (checkbox->icon) { + icon_y = ((obj->coords.y2 - obj->coords.y1) - (checkbox->icon->height)) / 2 + 1; + sgl_draw_icon(surf, &obj->area, align_pos.x, obj->coords.y1 + icon_y, checkbox->color, checkbox->alpha, checkbox->icon); + } + + sgl_draw_string(surf, &obj->area, align_pos.x + text_x, align_pos.y, checkbox->text, checkbox->color, checkbox->alpha, checkbox->font); + } + else if(evt->type == SGL_EVENT_PRESSED) { + checkbox->status = !checkbox->status; + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_DRAW_INIT) { + if(obj->coords.y2 < obj->coords.y1) { + obj->coords.y2 = obj->coords.y1 + unchecked_icon.height; + } + + if(obj->coords.x2 < obj->coords.x1) { + obj->coords.x2 = obj->coords.x1 + (checked_icon.width + sgl_font_get_string_width(checkbox->text, checkbox->font)); + } + } +} + + +/** + * @brief create a checkbox object + * @param parent parent of the checkbox + * @return checkbox object + */ +sgl_obj_t* sgl_checkbox_create(sgl_obj_t* parent) +{ + sgl_checkbox_t *checkbox = sgl_malloc(sizeof(sgl_checkbox_t)); + if(checkbox == NULL) { + SGL_LOG_ERROR("sgl_checkbox_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(checkbox, 0, sizeof(sgl_checkbox_t)); + + sgl_obj_t *obj = &checkbox->obj; + sgl_obj_init(&checkbox->obj, parent); + obj->construct_fn = sgl_checkbox_construct_cb; + obj->needinit = 1; + + checkbox->status = false; + checkbox->alpha = SGL_ALPHA_MAX; + checkbox->color = SGL_THEME_TEXT_COLOR; + checkbox->icon = &unchecked_icon; + + obj->coords.y2 = SGL_POS_INVALID; + obj->coords.x2 = SGL_POS_INVALID; + + sgl_obj_set_clickable(obj); + + checkbox->font = sgl_get_system_font(); + checkbox->text = " "; + return obj; +} diff --git a/User/system/sgl/widgets/checkbox/sgl_checkbox.h b/User/system/sgl/widgets/checkbox/sgl_checkbox.h new file mode 100644 index 0000000..653ecfa --- /dev/null +++ b/User/system/sgl/widgets/checkbox/sgl_checkbox.h @@ -0,0 +1,132 @@ +/* source/widgets/sgl_checkbox.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_CHECKBOX_H__ +#define __SGL_CHECKBOX_H__ + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct sgl_checkbox { + sgl_obj_t obj; + const char *text; + const sgl_font_t *font; + const sgl_icon_pixmap_t *icon; + sgl_color_t color; + uint8_t alpha; + bool status; +} sgl_checkbox_t; + + +/** + * @brief create a checkbox object + * @param parent parent of the checkbox + * @return checkbox object + */ +sgl_obj_t* sgl_checkbox_create(sgl_obj_t* parent); + +/** + * @brief set checkbox text and icon color + * @param obj checkbox object + * @param color color of text + * @return none + */ +static inline void sgl_checkbox_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + checkbox->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set checkbox text and icon alpha + * @param obj checkbox object + * @param alpha alpha of text + * @return none + */ +static inline void sgl_checkbox_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + checkbox->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set checkbox text + * @param obj checkbox object + * @param text text of checkbox + * @return none + */ +static inline void sgl_checkbox_set_text(sgl_obj_t *obj, const char *text) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + checkbox->text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set checkbox font + * @param obj checkbox object + * @param font font of checkbox + * @return none + */ +static inline void sgl_checkbox_set_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + checkbox->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set checkbox status + * @param obj checkbox object + * @param status status of checkbox + * @return none + */ +static inline void sgl_checkbox_set_status(sgl_obj_t *obj, bool status) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + checkbox->status = status; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get checkbox status + * @param obj checkbox object + * @return status of checkbox + */ +static inline bool sgl_checkbox_get_status(sgl_obj_t *obj) +{ + sgl_checkbox_t *checkbox = sgl_container_of(obj, sgl_checkbox_t, obj); + return checkbox->status; +} + + +#endif // !__SGL_CHECKBOX_H__ diff --git a/User/system/sgl/widgets/circle/sgl_circle.c b/User/system/sgl/widgets/circle/sgl_circle.c new file mode 100644 index 0000000..8a9787d --- /dev/null +++ b/User/system/sgl/widgets/circle/sgl_circle.c @@ -0,0 +1,94 @@ +/* source/widgets/sgl_circle.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_circle.h" + + +/** + * @brief construct function of the circle object + * @param surf pointer to the surface + * @param obj pointer to the object + * @param evt pointer to the event + * @return none + */ +static void sgl_circle_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + circle->desc.cx = (circle->obj.coords.x1 + circle->obj.coords.x2) / 2; + circle->desc.cy = (circle->obj.coords.y1 + circle->obj.coords.y2) / 2; + + sgl_draw_circle(surf, &obj->area, &circle->desc); + } + else if(evt->type == SGL_EVENT_DRAW_INIT) { + if(circle->desc.radius == -1) { + circle->desc.radius = (circle->obj.coords.y2 - circle->obj.coords.y1) / 2; + } + } +} + + +/** + * @brief create a circle object + * @param parent parent of the object + * @return pointer to the object + */ +sgl_obj_t* sgl_circle_create(sgl_obj_t* parent) +{ + sgl_circle_t *circle = sgl_malloc(sizeof(sgl_circle_t)); + if(circle == NULL) { + SGL_LOG_ERROR("sgl_circle_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(circle, 0, sizeof(sgl_circle_t)); + + sgl_obj_t *obj = &circle->obj; + sgl_obj_init(&circle->obj, parent); + obj->construct_fn = sgl_circle_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + obj->needinit = 1; + + circle->desc.alpha = SGL_ALPHA_MAX; + circle->desc.color = SGL_THEME_COLOR; + circle->desc.pixmap = NULL; + circle->desc.border = SGL_THEME_BORDER_WIDTH; + circle->desc.border_color = SGL_THEME_BORDER_COLOR; + circle->desc.cx = -1; + circle->desc.cy = -1; + circle->desc.radius = -1; + + return obj; +} diff --git a/User/system/sgl/widgets/circle/sgl_circle.h b/User/system/sgl/widgets/circle/sgl_circle.h new file mode 100644 index 0000000..0d1d6ce --- /dev/null +++ b/User/system/sgl/widgets/circle/sgl_circle.h @@ -0,0 +1,138 @@ +/* source/widgets/sgl_circle.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_CIRCLE_H__ +#define __SGL_CIRCLE_H__ + + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief draw a circle + * @obj: sgl general object + * @desc: circle description + */ +typedef struct sgl_circle { + sgl_obj_t obj; + sgl_draw_circle_t desc; +}sgl_circle_t; + + +/** + * @brief create a circle object + * @param parent parent of the object + * @return pointer to the object + */ +sgl_obj_t* sgl_circle_create(sgl_obj_t* parent); + + +/** + * @brief set the color of the circle + * @param obj pointer to the object + * @param color color of the circle + * @return none + */ +static inline void sgl_circle_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + circle->desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the radius of the circle + * @param obj pointer to the object + * @param radius radius of the circle + * @return none + */ +static inline void sgl_circle_set_radius(sgl_obj_t *obj, uint16_t radius) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + sgl_obj_set_radius(obj, radius); + circle->desc.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the alpha of the circle + * @param obj pointer to the object + * @param alpha alpha of the circle + * @return none + */ +static inline void sgl_circle_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + circle->desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the pixmap of the circle + * @param obj pointer to the object + * @param pixmap pixmap of the circle + * @return none + */ +static inline void sgl_circle_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + circle->desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the border color of the circle + * @param obj pointer to the object + * @param color border color of the circle + * @return none + */ +static inline void sgl_circle_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + circle->desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the border width of the circle + * @param obj pointer to the object + * @param width border width of the circle + * @return none + */ +static inline void sgl_circle_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_circle_t *circle = sgl_container_of(obj, sgl_circle_t, obj); + circle->desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_CIRCLE_H__ diff --git a/User/system/sgl/widgets/dropdown/sgl_dropdown.c b/User/system/sgl/widgets/dropdown/sgl_dropdown.c new file mode 100644 index 0000000..10deb35 --- /dev/null +++ b/User/system/sgl/widgets/dropdown/sgl_dropdown.c @@ -0,0 +1,329 @@ +/* source/widgets/sgl_dropdown.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sgl_dropdown.h" + +static const uint8_t dropdown_bitmap[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00, + 0x0c,0xfa,0x00,0x00,0x00,0x00,0x05,0xee,0x50, + 0x0c,0xff,0xa0,0x00,0x00,0x00,0x5e,0xfe,0x30, + 0x00,0xcf,0xfa,0x00,0x00,0x05,0xef,0xe3,0x00, + 0x00,0x0c,0xff,0xa0,0x00,0x5e,0xfe,0x30,0x00, + 0x00,0x00,0xcf,0xfa,0x05,0xef,0xe3,0x00,0x00, + 0x00,0x00,0x0c,0xff,0xae,0xfe,0x30,0x00,0x00, + 0x00,0x00,0x00,0xcf,0xff,0xe3,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0c,0xfe,0x30,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x53,0x00,0x00,0x00,0x00, +}; + + +static const sgl_icon_pixmap_t dropdown_icon = { + .bitmap = dropdown_bitmap, + .height = 10, + .width = 18, +}; + + +static void sgl_dropdown_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + int16_t icon_h = dropdown->option_h; + int16_t pos_x = 0, pos_y = 0, icon_y = 0; + sgl_dropdown_option_t *option = dropdown->head; + + sgl_rect_t body_area = { + .x1 = obj->coords.x1, + .x2 = obj->coords.x2, + .y1 = obj->coords.y1, + .y2 = obj->coords.y1 + dropdown->option_h, + }; + + sgl_rect_t icon_area = { + .x1 = obj->coords.x2 - dropdown_icon.width - dropdown->body_desc.radius, + .x2 = obj->coords.x2 - 2, + .y1 = obj->coords.y1, + .y2 = obj->coords.y2, + }; + + sgl_rect_t text_area = { + .x1 = obj->coords.x1 + 2, + .x2 = obj->coords.x2 - dropdown_icon.width - 5, + .y1 = obj->coords.y1, + .y2 = obj->coords.y2, + }; + + icon_y = obj->coords.y1 + (icon_h - dropdown_icon.height) / 2; + + if (evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &body_area, &dropdown->body_desc); + if (dropdown->is_open) { + sgl_draw_icon(surf, &obj->area, icon_area.x1, icon_y + 2, dropdown->text_color, dropdown->body_desc.alpha, &dropdown_icon); + } + else { + sgl_draw_icon(surf, &obj->area, icon_area.x1, icon_y, dropdown->text_color, dropdown->body_desc.alpha, &dropdown_icon); + } + + for (int i = 0; option != NULL; i++) { + if (i == dropdown->selected) { + break; + } + option = option->next; + } + + if (option != NULL) { + pos_x = text_area.x1 + dropdown->body_desc.radius; + pos_y = obj->coords.y1 + (icon_h - dropdown->font->font_height) / 2; + sgl_draw_string(surf, &text_area, pos_x, pos_y, option->text, dropdown->text_color, dropdown->body_desc.alpha, dropdown->font); + } + + if (dropdown->is_open) { + pos_y = body_area.y2; + option = dropdown->expend_start; + body_area.y1 = obj->coords.y1 + dropdown->option_h; + body_area.y2 = body_area.y1 + dropdown->expand_h - 1; + sgl_draw_rect(surf, &obj->area, &body_area, &dropdown->body_desc); + + for (int i = 0; option != NULL; i++) { + pos_x = text_area.x1 + dropdown->body_desc.radius; + sgl_draw_string(surf, &obj->area, pos_x, pos_y, option->text, dropdown->text_color, dropdown->body_desc.alpha, dropdown->font); + option = option->next; + pos_y += dropdown->font->font_height; + } + } + } + else if (evt->type == SGL_EVENT_MOVE_UP) { + + } + else if (evt->type == SGL_EVENT_MOVE_DOWN) { + + } + else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_CLICKED) { + dropdown->expand_h = dropdown->font->font_height * sgl_min(10, dropdown->option_num); + + if (dropdown->is_open) { + dropdown->is_open = false; + obj->coords.y2 -= dropdown->expand_h; + SGL_LOG_INFO("sgl_dropdown_construct_cb: selected %d %d %d", evt->pos.y, obj->coords.y2, dropdown->font->font_height); + if (evt->pos.y > obj->coords.y2) { + dropdown->selected = (evt->pos.y - obj->coords.y2) / dropdown->font->font_height; + } + } + else { + dropdown->is_open = true; + obj->coords.y2 += dropdown->expand_h; + } + + sgl_obj_set_dirty(obj); + dropdown->expend_start = dropdown->head; + } + else if (evt->type == SGL_EVENT_DRAW_INIT) { + dropdown->option_h = obj->coords.y2 - obj->coords.y1; + } +} + + +/** + * @brief create a dropdown object + * @param parent parent of the dropdown + * @return pointer to the dropdown object + */ +sgl_obj_t* sgl_dropdown_create(sgl_obj_t* parent) +{ + sgl_dropdown_t *dropdown = sgl_malloc(sizeof(sgl_dropdown_t)); + if(dropdown == NULL) { + SGL_LOG_ERROR("sgl_dropdown_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(dropdown, 0, sizeof(sgl_dropdown_t)); + + sgl_obj_t *obj = &dropdown->obj; + sgl_obj_init(&dropdown->obj, parent); + obj->construct_fn = sgl_dropdown_construct_cb; + obj->needinit = 1; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + sgl_obj_set_clickable(obj); + sgl_obj_set_movable(obj); + + dropdown->body_desc.alpha = SGL_THEME_ALPHA; + dropdown->body_desc.color = SGL_THEME_COLOR; + dropdown->body_desc.radius = 5; + dropdown->body_desc.border = 1; + dropdown->body_desc.border_color = SGL_THEME_BORDER_COLOR; + + dropdown->font = sgl_get_system_font(); + dropdown->head = NULL; + dropdown->is_open = false; + + dropdown->selected = -1; + dropdown->clicked = 0; + + return obj; +} + +/** + * @brief get the selected text of the dropdown + * @param obj pointer to the dropdown object + * @return pointer to the selected text + */ +const char *sgl_dropdown_get_selected_text(sgl_obj_t *obj) +{ + sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj; + sgl_dropdown_option_t *option = dropdown->head; + + for (int i = 0; i < dropdown->option_num; i++) { + if (i == dropdown->selected) { + return option->text; + } + option = option->next; + } + return NULL; +} + +/** + * @brief add an option to the dropdown + * @param obj pointer to the dropdown object + * @param text pointer to the text + * @return none + */ +void sgl_dropdown_add_option(sgl_obj_t *obj, const char *text) +{ + sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj; + sgl_dropdown_option_t *tail = dropdown->head; + sgl_dropdown_option_t *add = sgl_malloc(sizeof(sgl_dropdown_option_t)); + + if (add == NULL) { + SGL_LOG_ERROR("sgl_dropdown_add_option: malloc failed"); + return; + } + + if (tail == NULL) { + dropdown->head = add; + } + else { + while (tail != NULL) { + if (tail->next == NULL) { + tail->next = add; + break; + } + tail = (tail)->next; + } + } + + dropdown->option_num ++; + add->text = text; + add->next = NULL; + + if (dropdown->selected == -1) { + dropdown->selected = 0; + } + + sgl_obj_set_dirty(obj); +} + +/** + * @brief delete an option from the dropdown + * @param obj pointer to the dropdown object + * @param text pointer to the text + * @return none + */ +void sgl_dropdown_delete_option_by_text(sgl_obj_t *obj, const char *text) +{ + sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj; + sgl_dropdown_option_t *curr = dropdown->head; + sgl_dropdown_option_t *temp = dropdown->head; + sgl_dropdown_option_t *prev = NULL; + int deleted_index = 0; + + if (obj == NULL || text == NULL) { + return; + } + + while (curr != NULL) { + if (curr->text && strcmp(curr->text, text) == 0) { + break; + } + prev = curr; + curr = curr->next; + } + + if (curr == NULL) { + return; + } + + while (temp != curr) { + temp = temp->next; + deleted_index ++; + } + + if (prev == NULL) { + dropdown->head = curr->next; + } else { + prev->next = curr->next; + } + + sgl_free(curr); + dropdown->option_num--; + sgl_obj_set_dirty(obj); +} + +/** + * @brief delete an option from the dropdown + * @param obj pointer to the dropdown object + * @param index index of the option + * @return none + */ +void sgl_dropdown_delete_option_by_index(sgl_obj_t *obj, int index) +{ + sgl_dropdown_t *dropdown = (sgl_dropdown_t*)obj; + sgl_dropdown_option_t *curr = dropdown->head; + sgl_dropdown_option_t *prev = NULL; + + if (obj == NULL || index < 0 || index >= dropdown->option_num) { + return; + } + + for (int i = 0; i < index; i++) { + prev = curr; + curr = curr->next; + } + + if (prev == NULL) { + dropdown->head = curr->next; + } else { + prev->next = curr->next; + } + + sgl_free(curr); + dropdown->option_num--; +} diff --git a/User/system/sgl/widgets/dropdown/sgl_dropdown.h b/User/system/sgl/widgets/dropdown/sgl_dropdown.h new file mode 100644 index 0000000..97aa934 --- /dev/null +++ b/User/system/sgl/widgets/dropdown/sgl_dropdown.h @@ -0,0 +1,227 @@ +/* source/widgets/sgl_dropdown.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_DROPDOWN_H__ +#define __SGL_DROPDOWN_H__ + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct sgl_dropdown_option { + struct sgl_dropdown_option *next; + const char *text; +} sgl_dropdown_option_t; + + +/** + * @brief sgl dropdown struct + * @desc: text description + */ +typedef struct sgl_dropdown { + sgl_obj_t obj; + sgl_draw_rect_t body_desc; + const sgl_font_t *font; + sgl_color_t text_color; + sgl_dropdown_option_t *head; + uint16_t option_num; + int16_t selected; + int16_t option_h; + int16_t expand_h; + sgl_dropdown_option_t *expend_start; + uint8_t clicked; + bool is_open; +}sgl_dropdown_t; + + +/** + * @brief create a dropdown object + * @param parent parent of the dropdown + * @return dropdown object + */ +sgl_obj_t* sgl_dropdown_create(sgl_obj_t* parent); + +/** + * @brief set dropdown object's color + * @param obj dropdown object + * @param color color + */ +static inline void sgl_dropdown_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->body_desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's border width + * @param obj dropdown object + * @param width border width + */ +static inline void sgl_dropdown_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->body_desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's border color + * @param obj dropdown object + * @param color border color + */ +static inline void sgl_dropdown_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->body_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's radius + * @param obj dropdown object + * @param radius radius + */ +static inline void sgl_dropdown_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + sgl_obj_set_radius(obj, radius); + dropdown->body_desc.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's pixmap + * @param obj dropdown object + * @param pixmap pixmap + */ +static inline void sgl_dropdown_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->body_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's alpha + * @param obj dropdown object + * @param alpha alpha + */ +static inline void sgl_dropdown_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->body_desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's text color + * @param obj dropdown object + * @param color text color + */ +static inline void sgl_dropdown_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's text font + * @param obj dropdown object + * @param font text font + * @return none + * @note font must be initialized + */ +static inline void sgl_dropdown_set_text_font(sgl_obj_t *obj, const sgl_font_t* font) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + dropdown->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set dropdown object's selected index + * @param obj dropdown object + * @param index selected index + * @return none + */ +static inline void sgl_dropdown_set_selected_index(sgl_obj_t *obj, int index) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + SGL_ASSERT(obj != NULL && index >= 0 && index < dropdown->option_num); + dropdown->selected = index; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get dropdown object's selected index + * @param obj dropdown object + * @return selected index + */ +static inline int sgl_dropdown_get_selected_index(sgl_obj_t *obj) +{ + sgl_dropdown_t *dropdown = sgl_container_of(obj, sgl_dropdown_t, obj); + return dropdown->selected; +} + +/** + * @brief get dropdown object's selected text + * @param obj dropdown object + * @return selected text + */ +const char *sgl_dropdown_get_selected_text(sgl_obj_t *obj); + +/** + * @brief add an option to the dropdown + * @param obj pointer to the dropdown object + * @param text pointer to the text + * @return none + */ +void sgl_dropdown_add_option(sgl_obj_t *obj, const char *text); + +/** + * @brief delete an option from the dropdown + * @param obj pointer to the dropdown object + * @param text pointer to the text + * @return none + */ +void sgl_dropdown_delete_option_by_text(sgl_obj_t *obj, const char *text); + +/** + * @brief delete an option from the dropdown + * @param obj pointer to the dropdown object + * @param index index of the option + * @return none + */ +void sgl_dropdown_delete_option_by_index(sgl_obj_t *obj, int index); + + +#endif // !__SGL_DROPDOWN_H__ diff --git a/User/system/sgl/widgets/ext_img/sgl_ext_img.c b/User/system/sgl/widgets/ext_img/sgl_ext_img.c new file mode 100644 index 0000000..ec290a9 --- /dev/null +++ b/User/system/sgl/widgets/ext_img/sgl_ext_img.c @@ -0,0 +1,249 @@ +/* source/widgets/sgl_ext_img.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_ext_img.h" + +static inline void ext_img_rle_init(sgl_ext_img_t *img) +{ + SGL_ASSERT(img != NULL); + img->index = 0; + img->remainder = 0; +} + +static inline void rle_decompress_line(sgl_ext_img_t *img, sgl_area_t *coords, sgl_area_t *area, sgl_color_t *out) +{ + uint8_t tmp_buf[8]; + uint8_t* read_ptr = NULL; + uint8_t* start_ptr = (uint8_t*)img->pixmap[img->pixmap_idx].bitmap.array; + uintptr_t start_addr = img->pixmap[img->pixmap_idx].bitmap.addr; + uint8_t format = img->pixmap->format; + uint32_t pix_value; + + for (int i = coords->x1; i <= coords->x2; i++) { + if (img->remainder == 0) { + if (img->read != NULL) { + read_ptr = tmp_buf; + img->read(start_addr + img->index, tmp_buf, sizeof(tmp_buf)); + } + else { + read_ptr = start_ptr + img->index; + } + + img->index ++; + img->remainder = read_ptr[0]; + + switch (format) { + case SGL_PIXMAP_FMT_RLE_RGB332: + pix_value = read_ptr[1]; + img->color = sgl_rgb332_to_color(pix_value); + img->pix_alpha = SGL_ALPHA_MAX; + img->index ++; + break; + case SGL_PIXMAP_FMT_RLE_ARGB2222: + pix_value = read_ptr[1]; + img->color = sgl_rgb222_to_color(pix_value); + img->pix_alpha = sgl_opa2_table[pix_value >> 6]; + img->index ++; + break; + case SGL_PIXMAP_FMT_RLE_RGB565: + pix_value = read_ptr[1] | (read_ptr[2] << 8); + img->color = sgl_rgb565_to_color(pix_value); + img->pix_alpha = SGL_ALPHA_MAX; + img->index += 2; + break; + case SGL_PIXMAP_FMT_RLE_ARGB4444: + pix_value = read_ptr[1] | (read_ptr[2] << 8); + img->color = sgl_rgb444_to_color(pix_value); + img->pix_alpha = sgl_opa4_table[pix_value >> 12]; + img->index += 2; + break; + case SGL_PIXMAP_FMT_RLE_RGB888: + pix_value = read_ptr[1] | (read_ptr[2] << 8) | (read_ptr[3] << 16); + img->color = sgl_rgb888_to_color(pix_value); + img->pix_alpha = SGL_ALPHA_MAX; + img->index += 3; + break; + case SGL_PIXMAP_FMT_RLE_ARGB8888: + pix_value = read_ptr[1] | (read_ptr[2] << 8) | (read_ptr[3] << 16); + img->color = sgl_rgb888_to_color(pix_value); + img->pix_alpha = read_ptr[4]; + img->index += 4; + break; + default: + break; + } + } + + if (out != NULL && i >= area->x1 && i <= area->x2) { + img->color = (img->pix_alpha == SGL_ALPHA_MAX ? img->color : sgl_color_mixer(img->color, *out, img->pix_alpha)); + *out = (img->alpha == SGL_ALPHA_MAX ? img->color : sgl_color_mixer(img->color, *out, img->alpha)); + out ++; + } + img->remainder --; + }; +} + + +static void sgl_ext_img_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_area_t clip = SGL_AREA_INVALID; + sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj); + const sgl_pixmap_t *pixmap = &ext_img->pixmap[ext_img->pixmap_idx]; + uintptr_t read_addr = pixmap->bitmap.addr; + uint8_t pix_byte = sgl_pixmal_get_bytes_per_pixel(pixmap); + sgl_color_t tmp_color, *buf = NULL, *blend = NULL; + size_t pix_value = 0; + size_t offset = 0; + + sgl_area_t area = { + .x1 = obj->coords.x1, + .y1 = obj->coords.y1, + .x2 = obj->coords.x1 + pixmap->width - 1, + .y2 = obj->coords.y1 + pixmap->height - 1, + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if (!sgl_surf_clip(surf, &obj->area, &clip)) { + return; + } + + if (pixmap->format < SGL_PIXMAP_FMT_RLE_RGB332) { + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + + uint8_t *pixmap_buf = (uint8_t*)pixmap->bitmap.array; + if(ext_img->read != NULL){ + pixmap_buf = (uint8_t*)sgl_malloc(pix_byte * (clip.x2 - clip.x1 + 1)); + } + + for (int y = clip.y1; y <= clip.y2; y++) { + blend = buf; + offset = ((((y - area.y1) * pixmap->width) + (clip.x1 - area.x1)) * pix_byte); + if(ext_img->read != NULL) { + ext_img->read(read_addr + offset, pixmap_buf, pix_byte * (clip.x2 - clip.x1 + 1)); + offset = 0; + } + for (int x = clip.x1; x <= clip.x2; x++) { + switch (pixmap->format) { + case SGL_PIXMAP_FMT_RGB332: + pix_value = pixmap_buf[offset]; + tmp_color = sgl_rgb332_to_color(pix_value); + break; + case SGL_PIXMAP_FMT_RGB565: + pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8); + tmp_color = sgl_rgb565_to_color(pix_value); + break; + case SGL_PIXMAP_FMT_ARGB2222: + pix_value = pixmap_buf[offset]; + tmp_color = sgl_rgb222_to_color(pix_value); + tmp_color = sgl_color_mixer(tmp_color, *blend, sgl_opa2_table[pix_value >> 6]); + break; + case SGL_PIXMAP_FMT_ARGB4444: + pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8); + tmp_color = sgl_rgb444_to_color(pix_value); + tmp_color = sgl_color_mixer(tmp_color, *blend, sgl_opa4_table[pix_value >> 12]); + break; + case SGL_PIXMAP_FMT_RGB888: + pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8) | (pixmap_buf[offset + 2] << 16); + tmp_color = sgl_rgb888_to_color(pix_value); + break; + case SGL_PIXMAP_FMT_ARGB8888: + pix_value = pixmap_buf[offset] | (pixmap_buf[offset + 1] << 8) | (pixmap_buf[offset + 2] << 16); + tmp_color = sgl_rgb888_to_color(pix_value); + tmp_color = sgl_color_mixer(tmp_color, *blend, pixmap_buf[offset + 3]); + break; + default: + break; + } + *blend = ext_img->alpha == SGL_ALPHA_MAX ? tmp_color : sgl_color_mixer(tmp_color, *blend, ext_img->alpha); + offset += pix_byte; + blend ++; + }; + buf += surf->w; + } + if(ext_img->read != NULL) { + sgl_free(pixmap_buf); + } + } + else { + /* RLE pixmap support */ + if (clip.y1 == surf->dirty->y1 || clip.y1 == obj->area.y1) { + ext_img->index = 0; + ext_img->remainder = 0; + for (int y = area.y1; y < clip.y1; y++) { + rle_decompress_line(ext_img, &area, &clip, NULL); + } + } + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, (clip.y1 - surf->y1)); + + for (int y = clip.y1; y <= clip.y2; y++) { + rle_decompress_line(ext_img, &area, &clip, buf); + buf += surf->w; + } + } + + if (ext_img->pixmap_auto && (clip.y2 == surf->dirty->y2 || clip.y2 == obj->area.y2)) { + uint32_t pixmap_idx = ext_img->pixmap_idx + 1; + ext_img->pixmap_idx = pixmap_idx >= ext_img->pixmap_num ? 0 : pixmap_idx; + sgl_obj_set_dirty(obj); + } + } +} + + +/** + * @brief create an ext_img object + * @param parent parent of the ext_img + * @return ext_img object + */ +sgl_obj_t* sgl_ext_img_create(sgl_obj_t* parent) +{ + sgl_ext_img_t *ext_img = sgl_malloc(sizeof(sgl_ext_img_t)); + if(ext_img == NULL) { + SGL_LOG_ERROR("sgl_ext_img_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(ext_img, 0, sizeof(sgl_ext_img_t)); + + sgl_obj_t *obj = &ext_img->obj; + sgl_obj_init(&ext_img->obj, parent); + obj->construct_fn = sgl_ext_img_construct_cb; + + ext_img->alpha = SGL_ALPHA_MAX; + ext_img->pixmap_idx = 0; + ext_img->pixmap_num = 1; + ext_img->pixmap_auto = 0; + + return obj; +} diff --git a/User/system/sgl/widgets/ext_img/sgl_ext_img.h b/User/system/sgl/widgets/ext_img/sgl_ext_img.h new file mode 100644 index 0000000..a19d698 --- /dev/null +++ b/User/system/sgl/widgets/ext_img/sgl_ext_img.h @@ -0,0 +1,224 @@ +/* source/widgets/sgl_ext_img.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_EXT_IMG_H__ +#define __SGL_EXT_IMG_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** + * description: + * 1. Extern Flash image object: + * you can use this object to draw image from external flash memory + * for example: + * void flash_port_read_data_from_flash(const size_t addr, uint8_t *buf, uint32_t len) + * { + * //read the data to the buf from the addr of flash + * Flash_Read(addr, buf, len); + * } + * sgl_pixmap_t test_pixmap = { + * .width = 142, + * .height = 69, + * .bitmap = addr_of_extern_flash, + * .format = SGL_PIXMAP_FMT_RGB565, + * }; + * sgl_obj_t *ext_img = sgl_ext_img_create(NULL); + * sgl_obj_set_pos(ext_img, 10, 10); + * sgl_obj_set_size(ext_img, 142, 69); + * sgl_ext_img_set_pixmap(ext_img, &test_pixmap); + * sgl_ext_img_set_read_ops(ext_img, flash_port_read_data_from_flash); + * + * 2. RLE compress image object: + * you can use this object to draw image from external flash memory + * for example: + * extern const uint8_t pixmap_data[19596]; + * sgl_pixmap_t test_pixmap = { + * .width = 142, + * .height = 69, + * .bitmap = pixmap_data, + * .format = SGL_PIXMAP_FMT_RLE_RGB565, + * }; + * sgl_obj_t *ext_img = sgl_ext_img_create(NULL); + * sgl_obj_set_pos(ext_img, 10, 10); + * sgl_obj_set_size(ext_img, 142, 69); + * sgl_ext_img_set_pixmap(ext_img, &test_pixmap); + * + * 3. Mult pixmap image object: + * you can use this object to draw image from external flash memory + * for example: + * void flash_port_read_data_from_flash(const size_t addr, uint8_t *buf, uint32_t len) + * { + * //read the data to the buf from the addr of flash + * Flash_Read(addr, buf, len); + * } + * sgl_pixmap_t test_pixmap[128] = { + * { + * .width = 142, + * .height = 69, + * .bitmap = addr_of_extern_flash_1, + * .format = SGL_PIXMAP_FMT_RGB565, + * }, + * { + * .width = 142, + * .height = 69, + * .bitmap = addr_of_extern_flash_2, + * .format = SGL_PIXMAP_FMT_RGB565, + * }, + * { + * .width = 142, + * .height = 69, + * .bitmap = addr_of_extern_flash_3, + * .format = SGL_PIXMAP_FMT_RGB565, + * }, + * ... + * }; + * sgl_obj_t *ext_img = sgl_ext_img_create(NULL); + * sgl_obj_set_pos(ext_img, 10, 10); + * sgl_obj_set_size(ext_img, 142, 69); + * sgl_ext_img_set_pixmap(ext_img, test_pixmap); + * sgl_ext_img_set_pixmap_num(ext_img, 128, true); + * sgl_ext_img_set_read_ops(ext_img, flash_port_read_data_from_flash); + */ + + /* TODO: add ext img buffer size config */ +#define SGL_EXT_IMG_BUFFER_SIZE (CONFIG_SGL_EXT_IMG_BUFFER) + +/** + * @brief sgl ext_img struct + * @obj: sgl general object + * @desc: pointer to ext_img draw descriptor + */ +typedef struct sgl_ext_img { + sgl_obj_t obj; + const sgl_pixmap_t *pixmap; + void (*read)(const size_t addr, uint8_t *buf, uint32_t len_bytes); + uint8_t alpha; + uint8_t pixmap_auto; + uint8_t pixmap_idx; + uint8_t pixmap_num; + /* RLE compress context */ + sgl_color_t color; + uint8_t remainder; + uint8_t pix_alpha; + uint32_t index; +#if CONFIG_SGL_EXT_IMG_BUFFER + uint8_t flash_buffer[SGL_EXT_IMG_BUFFER_SIZE]; +#endif +} sgl_ext_img_t; + +/** + * @brief create an ext_img object + * @param parent parent of the ext_img + * @return ext_img object + */ +sgl_obj_t* sgl_ext_img_create(sgl_obj_t* parent); + +/** + * @brief set ext_img pixmap + * @param obj ext_img object + * @param pixmap ext_img pixmap + * @return none + */ +static inline void sgl_ext_img_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + SGL_ASSERT(obj != NULL); + ((sgl_ext_img_t*)obj)->pixmap = pixmap; +} + +/** + * @brief set ext_img read operation + * @param obj ext_img object + * @param read ext_img read operation + * @return none + */ +static inline void sgl_ext_img_set_read_ops(sgl_obj_t *obj, void (*read)(const size_t addr, uint8_t *out, uint32_t len_bytes)) +{ + SGL_ASSERT(obj != NULL); + ((sgl_ext_img_t*)obj)->read = read; +} + +/** + * @brief set ext_img alpha + * @param obj ext_img object + * @param alpha ext_img alpha + * @return none + */ +static inline void sgl_ext_img_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + SGL_ASSERT(obj != NULL); + ((sgl_ext_img_t*)obj)->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set ext_img pixmap number + * @param obj ext_img object + * @param num ext_img pixmap number + * @param auto_refresh ext_img pixmap auto refresh + * @return none + * @note if auto_refresh is true, the ext_img will refresh automatically after pixmap flush conplete + * @warning the num max is 255 + */ +static inline void sgl_ext_img_set_pixmap_num(sgl_obj_t *obj, uint8_t num, bool auto_refresh) +{ + SGL_ASSERT(obj != NULL); + ((sgl_ext_img_t*)obj)->pixmap_num = num; + ((sgl_ext_img_t*)obj)->pixmap_auto = (uint8_t)auto_refresh; +} + +/** + * @brief set ext_img next pixmap + * @param obj ext_img object + * @return none + */ +static inline void sgl_ext_img_set_pixmap_next(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj); + uint32_t pixmap_idx = ext_img->pixmap_idx + 1; + ext_img->pixmap_idx = pixmap_idx >= ext_img->pixmap_num ? 0 : pixmap_idx; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set ext_img pixmap current index + * @param obj ext_img object + * @param index ext_img pixmap index + * @return none + */ +static inline void sgl_ext_img_set_pixmap_index(sgl_obj_t *obj, uint8_t index) +{ + SGL_ASSERT(obj != NULL); + sgl_ext_img_t *ext_img = sgl_container_of(obj, sgl_ext_img_t, obj); + ext_img->pixmap_idx = sgl_min(index, ext_img->pixmap_num - 1); + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_EXT_IMG_H__ diff --git a/User/system/sgl/widgets/icon/sgl_icon.c b/User/system/sgl/widgets/icon/sgl_icon.c new file mode 100644 index 0000000..6edc8ef --- /dev/null +++ b/User/system/sgl/widgets/icon/sgl_icon.c @@ -0,0 +1,81 @@ +/* source/widgets/sgl_icon.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_icon.h" + + +/** + * @brief icon construct callback + * @param surf pointer to surface + * @param obj pointer to object + * @param evt pointer to event + * @return none + */ +static void sgl_icon_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj); + sgl_pos_t icon_pos; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + icon_pos = sgl_get_icon_pos(&obj->area, icon->icon, 0, (sgl_align_type_t)icon->align); + sgl_draw_icon(surf, &obj->area, icon_pos.x, icon_pos.y, icon->color, icon->alpha, icon->icon); + } +} + + +/** + * @brief create icon object + * @param parent pointer to parent object + * @return pointer to icon object + */ +sgl_obj_t* sgl_icon_create(sgl_obj_t* parent) +{ + sgl_icon_t *icon = sgl_malloc(sizeof(sgl_icon_t)); + if(icon == NULL) { + SGL_LOG_ERROR("sgl_icon_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(icon, 0, sizeof(sgl_icon_t)); + + sgl_obj_t *obj = &icon->obj; + sgl_obj_init(&icon->obj, parent); + obj->construct_fn = sgl_icon_construct_cb; + + icon->alpha = SGL_THEME_ALPHA; + icon->icon = NULL; + icon->color = SGL_THEME_TEXT_COLOR; + icon->align = SGL_ALIGN_CENTER; + + return obj; +} diff --git a/User/system/sgl/widgets/icon/sgl_icon.h b/User/system/sgl/widgets/icon/sgl_icon.h new file mode 100644 index 0000000..66bb267 --- /dev/null +++ b/User/system/sgl/widgets/icon/sgl_icon.h @@ -0,0 +1,107 @@ +/* source/widgets/sgl_icon.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_ICON_H__ +#define __SGL_ICON_H__ + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct sgl_icon { + sgl_obj_t obj; + const sgl_icon_pixmap_t *icon; + sgl_color_t color; + uint8_t alpha; + uint8_t align; +} sgl_icon_t; + + +/** + * @brief create icon object + * @param parent pointer to parent object + * @return pointer to icon object + */ +sgl_obj_t* sgl_icon_create(sgl_obj_t* parent); + + +/** + * @brief set icon color + * @param obj pointer to icon object + * @param color icon color + * @return none + */ +static inline void sgl_icon_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj); + icon->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set icon alpha + * @param obj pointer to icon object + * @param alpha icon alpha + * @return none + */ +static inline void sgl_icon_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_icon_t *icon = sgl_container_of(obj, sgl_icon_t, obj); + icon->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set icon pixmap + * @param obj pointer to icon object + * @param icon pointer to icon pixmap + * @return none + */ +static inline void sgl_icon_set_icon(sgl_obj_t *obj, const sgl_icon_pixmap_t *icon) +{ + sgl_icon_t *icon_obj = sgl_container_of(obj, sgl_icon_t, obj); + icon_obj->icon = icon; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set icon align + * @param obj pointer to icon object + * @param align icon align + * @return none + */ +static inline void sgl_icon_set_align(sgl_obj_t *obj, sgl_align_type_t align) +{ + sgl_icon_t *icon_obj = sgl_container_of(obj, sgl_icon_t, obj); + icon_obj->align = align; + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_ICON_H__ diff --git a/User/system/sgl/widgets/keyboard/sgl_keyboard.c b/User/system/sgl/widgets/keyboard/sgl_keyboard.c new file mode 100644 index 0000000..a14a1f7 --- /dev/null +++ b/User/system/sgl/widgets/keyboard/sgl_keyboard.c @@ -0,0 +1,551 @@ +/* source/widgets/sgl_keyboard.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_keyboard.h" + + +#define KEYBOARD_ICON_ENTER ("\xEE\xA2\x86") +#define KEYBOARD_ICON_NEWLINE ("\xEE\xA6\xB8") +#define KEYBOARD_ICON_BACKSPACE ("\xEE\xA0\xBE") +#define KEYBOARD_ICON_KEYBD ("\xEE\xA6\xB7") +#define KEYBOARD_ICON_LEFT ("\xEE\xA8\xAA") +#define KEYBOARD_ICON_RIGHT ("\xEE\xA8\xAB") +#define KEYBOARD_ICON_INVALID (-1) + + +#define KEYBOARD_KEYMODE_UPPER (0) +#define KEYBOARD_KEYMODE_LOWER (1) +#define KEYBOARD_KEYMODE_SPEC (2) +#define KEYBOARD_KEYMODE_MAX (3) + +#define KEYBOARD_BTN_LINES (4) +#define KEYBOARD_BTN_COLUMNS (12) +#define KEYBOARD_BTN_NUM (40) + + +#define KEYBOARD_KEY_INVALID (-1) +#define KEYBOARD_KEY_TO_UPPER (255) +#define KEYBOARD_KEY_TO_LOWER (254) +#define KEYBOARD_KEY_TO_SPEC (253) +#define KEYBOARD_KEY_TO_CLOSE (252) + +#define KEYBOARD_KEY_MODE(x) ((x) >> 1) + +#define KEYBOARD_KEY_BACKSPACE (11) +#define KEYBOARD_KEY_NUMBER_BACKSPACE (10) +#define KEYBOARD_KEY_SPACE (37) +#define KEYBOARD_KEY_NEWLINE (22) +#define KEYBOARD_KEY_ENTER (39) +#define KEYBOARD_KEY_CLOSE (35) +#define KEYBOARD_KEY_LEFT (36) +#define KEYBOARD_KEY_RIGHT (38) + + +static const uint8_t font_bitmap[] = { + /* U+E83E "î ¾" */ + 0x00, 0x00, 0x05, 0xde, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xec, 0x30, 0x00, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf0, 0x00, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, + 0xff, 0xff, 0xf6, 0x7f, 0xff, 0xff, 0x49, 0xff, 0xff, 0xf0, 0x0d, 0xff, 0xff, 0xfd, 0x00, 0x7f, + 0xff, 0x40, 0x2f, 0xff, 0xff, 0x08, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0x50, 0x2e, 0xff, 0xff, + 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x20, 0x1e, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x00, 0x0d, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x00, 0x7f, + 0xff, 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x50, 0x1a, 0x00, 0x7f, 0xff, 0xff, 0xf0, 0x2f, + 0xff, 0xff, 0xff, 0x50, 0x1d, 0xfc, 0x00, 0x8f, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xe1, 0x1d, + 0xff, 0xfc, 0x02, 0xff, 0xff, 0xf0, 0x00, 0xcf, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xfc, 0xef, 0xff, + 0xff, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x90, 0x00, 0x00, 0x04, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, + + /* U+E886 "" */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1d, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, 0x1c, + 0x30, 0x00, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x6f, 0xf3, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x00, + 0x00, 0x08, 0xff, 0x30, 0x1d, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xf4, 0xdf, 0xb0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xb0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* U+E9B7 "" */ + 0x03, 0xcd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xc3, 0x00, 0xef, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0xff, 0xd0, 0x2e, 0x04, 0xc0, 0xc4, 0x0e, 0x20, 0xdf, 0xf1, 0x1f, 0xfd, 0x01, 0xe0, 0x3c, 0x0c, + 0x30, 0xe1, 0x0d, 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x1f, + 0xfd, 0x01, 0xe0, 0x3c, 0x0c, 0x30, 0xe1, 0x0d, 0xff, 0x11, 0xff, 0xd0, 0x1e, 0x03, 0xc0, 0xc3, + 0x0e, 0x10, 0xdf, 0xf1, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0xff, + 0xff, 0xff, 0xee, 0xee, 0xee, 0xef, 0xff, 0xff, 0xf1, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0xef, 0xff, 0xff, 0x10, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xf0, 0x0e, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x4c, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xee, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xf6, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, + + /* U+E9B8 "" */ + 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xfb, 0x00, 0x00, + 0x00, 0x00, 0x0b, 0xd1, 0x00, 0x00, 0xaf, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf1, 0x00, 0x0a, + 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf1, 0x00, 0xaf, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0d, 0xf1, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x08, 0xff, 0xfe, 0xee, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xe1, 0x00, 0x8f, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0xfe, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xe3, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* U+EA2A "" */ + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x1c, 0xf8, 0x00, 0x01, 0xcf, 0xc0, 0x00, 0x1c, 0xfc, 0x00, + 0x01, 0xcf, 0xc0, 0x00, 0x0c, 0xfc, 0x00, 0x00, 0x0b, 0xfd, 0x10, 0x00, 0x00, 0xbf, 0xd1, 0x00, + 0x00, 0x0b, 0xfd, 0x10, 0x00, 0x00, 0xbf, 0xd1, 0x00, 0x00, 0x0b, 0xf8, 0x00, 0x00, 0x00, 0x70, + + /* U+EA2B "" */ + 0x08, 0x10, 0x00, 0x00, 0x8f, 0xc1, 0x00, 0x00, 0x0c, 0xfc, 0x10, 0x00, 0x00, 0xcf, 0xc1, 0x00, + 0x00, 0x0c, 0xfc, 0x10, 0x00, 0x00, 0xcf, 0xc0, 0x00, 0x01, 0xdf, 0xb0, 0x00, 0x1d, 0xfb, 0x00, + 0x01, 0xdf, 0xb0, 0x00, 0x1d, 0xfb, 0x00, 0x00, 0x8f, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00 +}; + + +static const sgl_font_table_t font_table[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 192, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 368, .box_w = 23, .box_h = 18, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 207, .adv_w = 368, .box_w = 18, .box_h = 14, .ofs_x = 3, .ofs_y = 1}, + {.bitmap_index = 333, .adv_w = 368, .box_w = 21, .box_h = 20, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 543, .adv_w = 368, .box_w = 20, .box_h = 12, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 663, .adv_w = 368, .box_w = 8, .box_h = 12, .ofs_x = 7, .ofs_y = 2}, + {.bitmap_index = 711, .adv_w = 368, .box_w = 8, .box_h = 12, .ofs_x = 8, .ofs_y = 2} +}; + +static const uint32_t unicode_list_0[] = { + 0x0000, 0xe81e, 0xe866, 0xe997, 0xe998, 0xea0a, 0xea0b +}; + +static const sgl_font_unicode_t font_unicode[] = { + { .offset = 0x20, .len = 7, .list = unicode_list_0, .tab_offset = 1, } +}; + +const sgl_font_t keyboard_icon = { + .bitmap = font_bitmap, + .table = font_table, + .font_table_size = SGL_ARRAY_SIZE(font_table), + .font_height = 20, + .base_line = 2, + .bpp = 4, + .compress = 0, + .unicode = font_unicode, + .unicode_num = SGL_ARRAY_SIZE(font_unicode), +}; + + +static const char keyboard_key_ascii[KEYBOARD_KEYMODE_MAX][KEYBOARD_BTN_NUM] = { + { + KEYBOARD_KEY_TO_SPEC, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '\b', + KEYBOARD_KEY_TO_LOWER, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '\n', + '_', '-', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '.', ',', ':', + KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r' + }, + { + KEYBOARD_KEY_TO_SPEC, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '\b', + KEYBOARD_KEY_TO_UPPER, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', '\n', + '_', '-', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '.', ',', ':', + KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r' + }, + { + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\b', + KEYBOARD_KEY_TO_LOWER, '+', '-', '/', '*', '=', '%', '!', '?', '#', '<', '>', + '\\', '@', '$', '(', ')', '{', '}', '[', ']', ';', '\"', '\'', + KEYBOARD_KEY_TO_CLOSE, KEYBOARD_KEY_LEFT, ' ', KEYBOARD_KEY_RIGHT, '\r' + }, +}; + + +static const char keybd_btn_map[KEYBOARD_KEYMODE_MAX][KEYBOARD_BTN_NUM][4] = { + { + "1#", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "<<", + "abc", "A", "S", "D", "F", "G", "H", "J", "K", "L", "nl", + "_", "-", "Z", "X", "C", "V", "B", "N", "M", ".", ",", ":", + "kbd", "<", " ", ">", "OK" + }, + { + "1#", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "<<", + "ABC", "a", "s", "d", "f", "g", "h", "j", "k", "l", "nl", + "_", "-", "z", "x", "c", "v", "b", "n", "m", ".", ",", ":", + "kbd", "<", " ", ">", "OK" + }, + { + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "<<", + "abc", "+", "-", "/", "*", "=", "%", "!", "?", "#", "<", ">", + "\\", "@", "$", "(", ")", "{", "}", "[", "]", ";", "\"", "'", + "kbd", "<", " ", ">", "OK" + }, +}; + + +static const uint8_t keybd_btn_width[2][KEYBOARD_BTN_LINES][KEYBOARD_BTN_COLUMNS] = { + /* upper and lower mode */ + { + {5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7}, + {6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {2, 2, 6, 2, 2}, + }, + /* number mode and spec mode */ + { + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2}, + {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {2, 2, 6, 2, 2}, + }, +}; + + +static const uint8_t keybd_btn_height[KEYBOARD_BTN_LINES] = { + 1, 1, 1, 1 +}; + + +static const uint8_t keyboard_btn_count[2][KEYBOARD_BTN_LINES] = { + /* upper and lower mode */ + { + 12, 11, 12, 5 + }, + /* number mode and spec mode */ + { + 11, 12, 12, 5 + } +}; + + +static void keyboard_btn_handler(sgl_keyboard_t *keyboard) +{ + char *edit = keyboard->edit; + int index = keyboard->edit_max_len; + while (*edit && index) { + edit ++; + index --; + } + + if (keyboard->opcode == '\b') { + *(--edit) = '\0'; + return; + } + + if (index == 0) { + SGL_LOG_ERROR("keyboard edit buffer is full\n"); + return; + } + + switch (keyboard->opcode) { + case '\n': + case '\r': + *(edit++) = '\n'; + *(edit++) = '\0'; + break; + default : + *(edit++) = keyboard->opcode; + *(edit++) = '\0'; + break; + } +} + + +static const char* keyindex_is_icon(uint8_t mode, uint8_t index) +{ + if(index == KEYBOARD_KEY_NUMBER_BACKSPACE && (mode == KEYBOARD_KEYMODE_SPEC)) { + return KEYBOARD_ICON_BACKSPACE; + } + else if(index == KEYBOARD_KEY_BACKSPACE && (mode < KEYBOARD_KEYMODE_SPEC)) { + return KEYBOARD_ICON_BACKSPACE; + } + else if(index == KEYBOARD_KEY_ENTER) { + return KEYBOARD_ICON_ENTER; + } + else if(index == KEYBOARD_KEY_NEWLINE && (mode != KEYBOARD_KEYMODE_SPEC)) { + return KEYBOARD_ICON_NEWLINE; + } + else if(index == KEYBOARD_KEY_CLOSE) { + return KEYBOARD_ICON_KEYBD; + } + else if(index == KEYBOARD_KEY_LEFT) { + return KEYBOARD_ICON_LEFT; + } + else if(index == KEYBOARD_KEY_RIGHT) { + return KEYBOARD_ICON_RIGHT; + } + + return NULL; +} + + +static inline uint8_t keyboard_index_to_ascii(uint8_t keymode, uint8_t index) +{ + return keyboard_key_ascii[keymode][index]; +} + + +static int8_t keyboard_pos_to_index(int16_t x, int16_t y, sgl_keyboard_t *keyboard, int16_t width, int16_t height) +{ + sgl_obj_t *obj = &keyboard->obj; + int16_t index = 0, x_index = -1, y_index = -1, key_mode = KEYBOARD_KEY_MODE(keyboard->key_mode); + int16_t btn_width[KEYBOARD_BTN_COLUMNS] = {0}; + int16_t btn_height[KEYBOARD_BTN_LINES] = {0}; + sgl_rect_t btn = {0}; + + /* calculate button height */ + sgl_split_len(keybd_btn_height, KEYBOARD_BTN_LINES, height, keyboard->key_margin, btn_height); + btn.y1 = obj->coords.y1; + for(int i = 0; i < KEYBOARD_BTN_LINES; i++) { + btn.y1 += keyboard->key_margin; + btn.y2 = btn.y1 + btn_height[i] - 1; + + if(y >= btn.y1 && y <= btn.y2) { + y_index = i; + break; + } + btn.y1 += btn_height[i]; + } + + if(y_index < 0 || y_index >= KEYBOARD_BTN_LINES) { + return -1; + } + + sgl_split_len(keybd_btn_width[key_mode][y_index], keyboard_btn_count[key_mode][y_index], width, keyboard->key_margin, btn_width); + + btn.x1 = obj->coords.x1; + for(int i = 0; i < keyboard_btn_count[key_mode][y_index]; i++) { + btn.x1 += keyboard->key_margin; + btn.x2 = btn.x1 + btn_width[i] - 1; + if(x >= btn.x1 && x <= btn.x2) { + x_index = i; + break; + } + btn.x1 += btn_width[i]; + } + + if(x_index < 0 || x_index >= keyboard_btn_count[key_mode][y_index]) { + return -1; + } + + for(int i = 0; i < y_index; i ++) { + index += keyboard_btn_count[key_mode][i]; + } + + return (index + x_index); +} + + +/** + * @brief keyboard constructor function + * @param surf: pointer to surface + * @param obj: pointer to keyboard object + * @param evt: pointer to event + * @return none + */ +static void sgl_keyboard_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + int16_t body_w = obj->coords.x2 - obj->coords.x1 + 1; + int16_t body_h = obj->coords.y2 - obj->coords.y1 + 1; + + int8_t index = 0, key_mode = KEYBOARD_KEY_MODE(keyboard->key_mode); + sgl_color_t btn_color = keyboard->btn_desc.color; + int16_t text_x = 0, text_y = 0; + const char *text = NULL; + const sgl_font_t *font = keyboard->font; + int16_t btn_width[KEYBOARD_BTN_COLUMNS] = {0}; + int16_t btn_height[KEYBOARD_BTN_LINES] = {0}; + sgl_rect_t btn_coords = {0}, btn_area = {0}; + + /* calculate button height */ + sgl_split_len(keybd_btn_height, KEYBOARD_BTN_LINES, body_h, keyboard->key_margin, btn_height); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &obj->coords, &keyboard->body_desc); + + btn_coords.y1 = obj->coords.y1; + + for(int i = 0; i < KEYBOARD_BTN_LINES; i++) { + sgl_split_len(keybd_btn_width[key_mode][i], keyboard_btn_count[key_mode][i], body_w, keyboard->key_margin, btn_width); + + btn_coords.x1 = obj->coords.x1; + btn_coords.y1 += keyboard->key_margin; + btn_coords.y2 = btn_coords.y1 + btn_height[i] - 1; + + for(int j = 0; j < keyboard_btn_count[key_mode][i]; j++) { + btn_coords.x1 += keyboard->key_margin; + btn_coords.x2 = btn_coords.x1 + btn_width[j] - 1; + btn_area = btn_coords; + if (!sgl_area_selfclip(&btn_area, &obj->area)) { + sgl_area_init(&btn_area); + } + + if(index == keyboard->key_index) { + keyboard->btn_desc.color = sgl_color_mixer(btn_color, keyboard->text_color, 128); + } + else { + keyboard->btn_desc.color = btn_color; + } + sgl_draw_rect(surf, &btn_area, &btn_coords, &keyboard->btn_desc); + + text = keyindex_is_icon(keyboard->key_mode, index); + if (text != NULL) { + font = &keyboard_icon; + } + else { + font = keyboard->font; + text = keybd_btn_map[keyboard->key_mode][index]; + } + text_x = btn_coords.x1 + (btn_width[j] - sgl_font_get_string_width(text, font)) / 2; + text_y = btn_coords.y1 + (btn_height[i] - font->font_height) / 2; + sgl_draw_string(surf, &btn_area, text_x, text_y, text, keyboard->text_color, SGL_ALPHA_MAX, font); + + btn_coords.x1 += btn_width[j]; + index ++; + } + + btn_coords.y1 += btn_height[i]; + } + + keyboard->btn_desc.color = btn_color; + } + else if(evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_OPTION_TAP) { + if (evt->type == SGL_EVENT_PRESSED) { + index = keyboard_pos_to_index(evt->pos.x, evt->pos.y, keyboard, body_w, body_h); + if(index < 0) { + return; + } + keyboard->key_index = index; + } + + uint8_t key_ascii = keyboard_index_to_ascii(keyboard->key_mode, index); + if(key_ascii == KEYBOARD_KEY_TO_UPPER) { + keyboard->key_mode = KEYBOARD_KEYMODE_UPPER; + keyboard->key_index = KEYBOARD_KEY_INVALID; + } + else if(key_ascii == KEYBOARD_KEY_TO_LOWER) { + keyboard->key_mode = KEYBOARD_KEYMODE_LOWER; + keyboard->key_index = KEYBOARD_KEY_INVALID; + } + else if(key_ascii == KEYBOARD_KEY_TO_SPEC) { + keyboard->key_mode = KEYBOARD_KEYMODE_SPEC; + keyboard->key_index = KEYBOARD_KEY_INVALID; + } + else if(key_ascii == KEYBOARD_KEY_TO_CLOSE) { + sgl_obj_set_destroyed(obj); + return; + } + else { + keyboard->opcode = key_ascii; + if (keyboard->edit) { + keyboard_btn_handler(keyboard); + } + } + + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + keyboard->key_index = KEYBOARD_KEY_INVALID; + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_DRAW_INIT) { + keyboard->opcode = 0; + keyboard->key_index = KEYBOARD_KEY_INVALID; + + if (keyboard->key_margin == 0) { + keyboard->key_margin = sgl_max(body_w / 128, 1); + } + + if (keyboard->btn_desc.radius == 0) { + keyboard->btn_desc.radius = sgl_max(keyboard->key_margin, 2); + } + + SGL_ASSERT(keyboard->font != NULL); + } + else if (evt->type == SGL_EVENT_OPTION_WALK) { + keyboard->key_index ++; + + if (keyboard->key_index >= KEYBOARD_BTN_NUM) { + keyboard->key_index = 0; + } + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create keyboard object + * @param parent parent of object + * @return keyboard object + */ +sgl_obj_t* sgl_keyboard_create(sgl_obj_t* parent) +{ + sgl_keyboard_t *keyboard = sgl_malloc(sizeof(sgl_keyboard_t)); + if(keyboard == NULL) { + SGL_LOG_ERROR("sgl_keyboard_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(keyboard, 0, sizeof(sgl_keyboard_t)); + + sgl_obj_t *obj = &keyboard->obj; + sgl_obj_init(&keyboard->obj, parent); + obj->construct_fn = sgl_keyboard_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + obj->clickable = 1; + obj->needinit = 1; + + keyboard->body_desc.alpha = SGL_THEME_ALPHA; + keyboard->body_desc.color = SGL_THEME_COLOR; + keyboard->body_desc.radius = SGL_THEME_RADIUS; + keyboard->body_desc.border = 1; + keyboard->body_desc.border_color = SGL_THEME_BORDER_COLOR; + keyboard->body_desc.pixmap = NULL; + keyboard->text_color = SGL_THEME_TEXT_COLOR; + + keyboard->btn_desc.alpha = SGL_THEME_ALPHA; + keyboard->btn_desc.color = sgl_color_mixer(SGL_THEME_BORDER_COLOR, SGL_THEME_COLOR, 64); + keyboard->btn_desc.radius = 4; + keyboard->btn_desc.border = 0; + keyboard->btn_desc.border_color = SGL_THEME_BORDER_COLOR; + keyboard->btn_desc.pixmap = NULL; + + keyboard->key_mode = KEYBOARD_KEYMODE_LOWER; + + keyboard->key_margin = 0; + keyboard->font = sgl_get_system_font(); + + return obj; +} + diff --git a/User/system/sgl/widgets/keyboard/sgl_keyboard.h b/User/system/sgl/widgets/keyboard/sgl_keyboard.h new file mode 100644 index 0000000..4e6331c --- /dev/null +++ b/User/system/sgl/widgets/keyboard/sgl_keyboard.h @@ -0,0 +1,275 @@ +/* source/widgets/sgl_keyboard.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_KEYBOARD_H__ +#define __SGL_KEYBOARD_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl keyboard struct + * @obj: sgl general object + * @body_desc: pointer to sgl_draw_rect_t descriptor + */ +typedef struct sgl_keyboard { + sgl_obj_t obj; + sgl_draw_rect_t body_desc; + sgl_draw_rect_t btn_desc; + const sgl_font_t *font; + char *edit; + sgl_color_t text_color; + uint8_t opcode; + uint8_t key_margin; + int8_t key_index; + uint8_t key_mode; + uint32_t edit_max_len; +} sgl_keyboard_t; + + +/** + * @brief create keyboard object + * @param parent parent of object + * @return keyboard object + */ +sgl_obj_t* sgl_keyboard_create(sgl_obj_t* parent); + + +/** + * @brief set keyboard color + * @param obj keyboard object + * @param color color + * @return none + */ +static inline void sgl_keyboard_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->body_desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard alpha + * @param obj keyboard object + * @param alpha alpha [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->body_desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard radius + * @param obj keyboard object + * @param radius radius [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + sgl_obj_set_radius(obj, radius); + keyboard->body_desc.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard pixmap + * @param obj keyboard object + * @param pixmap pixmap + * @return none + */ +static inline void sgl_keyboard_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->body_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard border color + * @param obj keyboard object + * @param color border color + * @return none + * + */ +static inline void sgl_keyboard_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->body_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard border width + * @param obj keyboard object + * @param width border width [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard text color + * @param obj keyboard object + * @param color text color + * @return none + */ +static inline void sgl_keyboard_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard text font + * @param obj keyboard object + * @param font text font + * @return none + */ +static inline void sgl_keyboard_set_text_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button radius + * @param obj keyboard object + * @param radius button radius [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_btn_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.radius = radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button alpha + * @param obj keyboard object + * @param alpha button alpha [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_btn_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button color + * @param obj keyboard object + * @param color button color + * @return none + */ +static inline void sgl_keyboard_set_btn_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button pixmap + * @param obj keyboard object + * @param pixmap button pixmap + * @return none + */ +static inline void sgl_keyboard_set_btn_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button border color + * @param obj keyboard object + * @param color button border color + * @return none + */ +static inline void sgl_keyboard_set_btn_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set keyboard button border width + * @param obj keyboard object + * @param width button border width [0 ~ 255] + * @return none + */ +static inline void sgl_keyboard_set_btn_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->btn_desc.border = width; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get keyboard opcode + * @param obj keyboard object + * @return opcode [0 ~ 255] + */ +static inline uint8_t sgl_keyboard_get_opcode(sgl_obj_t *obj) +{ + return ((sgl_keyboard_t*)obj)->opcode; +} + + +/** + * @brief set keyboard text buffer + * @param obj keyboard object + * @param buffer edit buffer + * @param buf_max_len edit buffer max length + */ +static inline void sgl_keyboard_set_textarea(sgl_obj_t *obj, char *buffer, int buf_max_len) +{ + sgl_keyboard_t *keyboard = sgl_container_of(obj, sgl_keyboard_t, obj); + keyboard->edit = buffer; + keyboard->edit_max_len = buf_max_len; +} + + +#endif // !__SGL_KEYBOARD_H__ diff --git a/User/system/sgl/widgets/label/sgl_label.c b/User/system/sgl/widgets/label/sgl_label.c new file mode 100644 index 0000000..c5e6247 --- /dev/null +++ b/User/system/sgl/widgets/label/sgl_label.c @@ -0,0 +1,131 @@ +/* source/widgets/sgl_label.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_label.h" + + +/** + * @brief construct the label object + * @param surf pointer to the surface + * @param obj pointer to the label object + * @param evt pointer to the event + * @return none + */ +static void sgl_label_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + sgl_pos_t align_pos; + + SGL_ASSERT(label->font != NULL); + + if (evt->type == SGL_EVENT_DRAW_MAIN) { + if (label->bg_flag) { + sgl_draw_fill_rect(surf, &obj->area, &obj->coords, obj->radius, label->bg_color, label->alpha); + } + + align_pos = sgl_get_text_pos(&obj->coords, label->font, label->text, 0, (sgl_align_type_t)label->align); + +#if (CONFIG_SGL_LABEL_ROTATION) + if (label->rota == 0) { +#endif + sgl_draw_string(surf, &obj->area, align_pos.x + label->transform.offset.offset_x, + align_pos.y + label->transform.offset.offset_y, + label->text, label->color, label->alpha, label->font); +#if (CONFIG_SGL_LABEL_ROTATION) + } + else { + const int16_t width = obj->area.x2 - obj->area.x1 + 1; + const int16_t height = obj->area.y2 - obj->area.y1 + 1; + const uint32_t buf_size = width * height; + + sgl_color_t *temp_buf = sgl_malloc(buf_size * sizeof(sgl_color_t)); + if (temp_buf == NULL) { + SGL_LOG_ERROR("sgl_label_construct_cb: malloc rotation temp buffer failed"); + return; + } + + for (uint32_t i = 0; i < buf_size; i++) { + temp_buf[i] = label->bg_color; + } + + sgl_surf_t temp_surf = { + .x1 = 0, + .y1 = 0, + .x2 = width - 1, + .y2 = height - 1, + .buffer = temp_buf, + .w = width, + .h = height, + .dirty = NULL + }; + + sgl_draw_string(&temp_surf, &obj->area, align_pos.x, align_pos.y, + label->text, label->color, label->alpha, label->font); + sgl_draw_xform_surf(surf, &temp_surf, &obj->area, obj->coords.x1, obj->coords.y1, label->transform.rotation); + + sgl_free(temp_buf); + } +#endif + } +} + + +/** + * @brief create a label object + * @param parent parent of the label + * @return pointer to the label object + */ +sgl_obj_t* sgl_label_create(sgl_obj_t* parent) +{ + sgl_label_t *label = sgl_malloc(sizeof(sgl_label_t)); + if(label == NULL) { + SGL_LOG_ERROR("sgl_label_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(label, 0, sizeof(sgl_label_t)); + + sgl_obj_t *obj = &label->obj; + sgl_obj_init(&label->obj, parent); + obj->construct_fn = sgl_label_construct_cb; + + label->alpha = SGL_ALPHA_MAX; + label->bg_flag = 0; + label->color = SGL_THEME_TEXT_COLOR; + label->text = ""; + label->transform.rotation = 0; + label->rota = 0; + label->font = sgl_get_system_font(); + + return obj; +} diff --git a/User/system/sgl/widgets/label/sgl_label.h b/User/system/sgl/widgets/label/sgl_label.h new file mode 100644 index 0000000..e0bf3b4 --- /dev/null +++ b/User/system/sgl/widgets/label/sgl_label.h @@ -0,0 +1,191 @@ +/* source/widgets/sgl_label.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LABEL_H__ +#define __SGL_LABEL_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl label object + * @obj: sgl general object + * @desc: draw task descriptor + */ +typedef struct sgl_label { + sgl_obj_t obj; + const char *text; + const sgl_font_t *font; + sgl_color_t color; + sgl_color_t bg_color; + uint8_t alpha; + uint8_t align: 6; + uint8_t bg_flag : 1; + uint8_t rota : 1; + union { + struct { + int8_t offset_x; + int8_t offset_y; + } offset; + int16_t rotation; + } transform; +}sgl_label_t; + + +/** + * @brief create a label object + * @param parent parent of the label + * @return pointer to the label object + */ +sgl_obj_t* sgl_label_create(sgl_obj_t* parent); + + +/** + * @brief set label text + * @param obj pointer to the label object + * @param text text to be set + * @return none + */ +static inline void sgl_label_set_text(sgl_obj_t *obj, const char *text) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label font + * @param obj pointer to the label object + * @param font pointer to the font + * @return none + */ +static inline void sgl_label_set_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label text color + * @param obj pointer to the label object + * @param color color to be set + * @return none + */ +static inline void sgl_label_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label background color + * @param obj pointer to the label object + * @param color color to be set + * @return none + */ +static inline void sgl_label_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->bg_color = color; + label->bg_flag = 1; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label radius + * @param obj pointer to the label object + * @param radius radius to be set + * @return none + */ +static inline void sgl_label_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label text align + * @param obj pointer to the label object + * @param align align to be set + * @return none + */ +static inline void sgl_label_set_text_align(sgl_obj_t *obj, sgl_align_type_t align) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->align = align; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label alpha + * @param obj pointer to the label object + * @param alpha alpha to be set + * @return none + */ +static inline void sgl_label_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label text offset + * @param obj pointer to the label object + * @param offset_x offset_x to be set + * @param offset_y offset_y to be set + * @return none + */ +static inline void sgl_label_set_text_offset(sgl_obj_t *obj, int8_t offset_x, int8_t offset_y) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->transform.offset.offset_x = offset_x; + label->transform.offset.offset_y = offset_y; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set label text rotation + * @param obj pointer to the label object + * @param text_rotation text rotation angle (0-360 degree) + * @return none + */ +static inline void sgl_label_set_text_rotation(sgl_obj_t *obj, int16_t text_rotation) +{ + sgl_label_t *label = sgl_container_of(obj, sgl_label_t, obj); + label->transform.rotation = text_rotation % 360; + if (label->transform.rotation < 0) label->transform.rotation += 360; + label->rota = label->transform.rotation ? 1 : 0; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_LABEL_H__ diff --git a/User/system/sgl/widgets/led/sgl_led.c b/User/system/sgl/widgets/led/sgl_led.c new file mode 100644 index 0000000..416720f --- /dev/null +++ b/User/system/sgl/widgets/led/sgl_led.c @@ -0,0 +1,136 @@ +/* source/widgets/sgl_led.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_led.h" + + +static void sgl_led_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + int16_t cx = 0, cy = 0; + sgl_color_t color = led->status ? led->on_color : led->off_color; + sgl_color_t *buf = NULL, *blend = NULL; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_area_t clip; + + cx = (led->obj.coords.x1 + led->obj.coords.x2) / 2; + cy = (led->obj.coords.y1 + led->obj.coords.y2) / 2; + + if (!sgl_surf_clip(surf, &obj->area, &clip)) { + return; + } + + sgl_area_t c_rect = { + .x1 = cx - obj->radius, + .x2 = cx + obj->radius, + .y1 = cy - obj->radius, + .y2 = cy + obj->radius + }; + if (!sgl_area_selfclip(&clip, &c_rect)) { + return; + } + + int y2 = 0, real_r2 = 0, edge_alpha = 0; + int r2 = sgl_pow2(obj->radius); + int r2_edge = sgl_pow2(obj->radius + 1); + int ds_alpha = SGL_ALPHA_MIN; + + buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, clip.y1 - surf->y1); + for (int y = clip.y1; y <= clip.y2; y++) { + y2 = sgl_pow2(y - cy); + blend = buf; + + for (int x = clip.x1; x <= clip.x2; x++, blend++) { + real_r2 = sgl_pow2(x - cx) + y2; + if (real_r2 >= r2_edge) { + if(x > cx) + break; + continue; + } + else if (real_r2 >= r2) { + edge_alpha = SGL_ALPHA_MAX - sgl_sqrt_error(real_r2); + sgl_color_t color_mix = sgl_color_mixer(led->bg_color, *blend, edge_alpha); + *blend = sgl_color_mixer(color_mix, *blend, led->alpha); + } + else { + ds_alpha = real_r2 * SGL_ALPHA_NUM / r2; + ds_alpha = sgl_pow2(ds_alpha) / SGL_ALPHA_NUM ; + *blend = sgl_color_mixer(sgl_color_mixer(led->bg_color, color, ds_alpha), *blend, led->alpha);//SGL_THEME_BG_COLOR + } + } + buf += surf->w; + } + } + else if (evt->type == SGL_EVENT_DRAW_INIT) { + if (obj->radius == SGL_RADIUS_INVALID) { + sgl_obj_set_radius(obj, SGL_POS_MAX); + } + } + else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_RELEASED) { + if (obj->event_fn) { + obj->event_fn(evt); + } + } +} + + +/** + * @brief create a led object + * @param parent parent of the led + * @return led object + */ +sgl_obj_t* sgl_led_create(sgl_obj_t* parent) +{ + sgl_led_t *led = sgl_malloc(sizeof(sgl_led_t)); + if(led == NULL) { + SGL_LOG_ERROR("sgl_led_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(led, 0, sizeof(sgl_led_t)); + + sgl_obj_t *obj = &led->obj; + sgl_obj_init(&led->obj, parent); + obj->construct_fn = sgl_led_construct_cb; + + obj->needinit = 1; + + led->alpha = SGL_ALPHA_MAX; + led->on_color = SGL_THEME_COLOR; + led->off_color = SGL_THEME_BG_COLOR; + led->bg_color = SGL_THEME_BG_COLOR; + obj->radius = SGL_RADIUS_INVALID; + + return obj; +} diff --git a/User/system/sgl/widgets/led/sgl_led.h b/User/system/sgl/widgets/led/sgl_led.h new file mode 100644 index 0000000..b44dd23 --- /dev/null +++ b/User/system/sgl/widgets/led/sgl_led.h @@ -0,0 +1,157 @@ +/* source/widgets/sgl_led.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LED_H__ +#define __SGL_LED_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl led struct + * @obj: sgl general object + * @desc: pointer to led draw descriptor + */ +typedef struct sgl_led { + sgl_obj_t obj; + uint8_t alpha; + bool status; + sgl_color_t on_color; + sgl_color_t off_color; + sgl_color_t bg_color; + +}sgl_led_t; + + +/** + * @brief create a led object + * @param parent parent of the led + * @return led object + */ +sgl_obj_t* sgl_led_create(sgl_obj_t* parent); + + +/** + * @brief set the color of the led + * @param obj led object + * @param color color of the led + * @return none + */ +static inline void sgl_led_set_on_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + led->on_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the off color of the led + * @param obj led object + * @param color off color of the led + * @return none + */ +static inline void sgl_led_set_off_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + led->off_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set the background color of the led + * @param obj led object + * @param color background color of the led + * @return none + */ +static inline void sgl_led_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + led->bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the alpha of the led + * @param obj led object + * @param alpha alpha of the led + * @return none + */ +static inline void sgl_led_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + led->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the status of the led + * @param obj led object + * @param status status of the led + * @return none + */ +static inline void sgl_led_set_status(sgl_obj_t *obj, bool status) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + led->status = status; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get the status of the led + * @param obj led object + * @return status of the led + */ +static inline bool sgl_led_get_status(sgl_obj_t *obj) +{ + sgl_led_t *led = sgl_container_of(obj, sgl_led_t, obj); + return led->status; +} + +/** + * @brief turn on the led + * @param obj led object + * @return none + */ +static inline void sgl_led_on(sgl_obj_t *obj) +{ + sgl_led_set_status(obj, true); +} + +/** + * @brief turn off the led + * @param obj led object + * @return none + */ +static inline void sgl_led_off(sgl_obj_t *obj) +{ + sgl_led_set_status(obj, false); +} + +#endif // !__SGL_LED_H__ diff --git a/User/system/sgl/widgets/line/sgl_line.c b/User/system/sgl/widgets/line/sgl_line.c new file mode 100644 index 0000000..44ccc30 --- /dev/null +++ b/User/system/sgl/widgets/line/sgl_line.c @@ -0,0 +1,132 @@ +/* source/widgets/sgl_line.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_line.h" + + +static void sgl_line_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj); + sgl_draw_line_t desc; + + desc.x1 = obj->coords.x1; + desc.y1 = obj->coords.y1; + desc.x2 = obj->coords.x2; + desc.y2 = obj->coords.y2; + desc.color = line->color; + desc.alpha = line->alpha; + desc.width = obj->border; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if (line->x_swap) { + sgl_swap(&desc.x1, &desc.x2); + } + if (line->y_swap) { + sgl_swap(&desc.y1, &desc.y2); + } + + sgl_draw_line(surf, &obj->parent->area, &desc); + } +} + + +/** + * @brief create a line object + * @param parent parent of the line + * @return line object + */ +sgl_obj_t* sgl_line_create(sgl_obj_t* parent) +{ + sgl_line_t *line = sgl_malloc(sizeof(sgl_line_t)); + if(line == NULL) { + SGL_LOG_ERROR("sgl_line_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(line, 0, sizeof(sgl_line_t)); + + sgl_obj_t *obj = &line->obj; + sgl_obj_init(&line->obj, parent); + obj->construct_fn = sgl_line_construct_cb; + + line->color = SGL_THEME_BG_COLOR; + line->alpha = SGL_ALPHA_MAX; + obj->border = 1; + + return obj; +} + + +/** + * @brief set line start position + * @param obj line object + * @param x start x position + * @param y start y position + * @return none + */ +void sgl_line_set_pos(sgl_obj_t *obj, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + SGL_ASSERT(obj != NULL); + int16_t _x1, _y1, _x2, _y2; + sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj); + + _x1 = obj->parent->coords.x1 + x1; + _x2 = obj->parent->coords.x1 + x2; + _y1 = obj->parent->coords.y1 + y1; + _y2 = obj->parent->coords.y1 + y2; + + if (_x1 > _x2) { + sgl_swap(&_x1, &_x2); + line->x_swap = 1; + } + else { + line->x_swap = 0; + } + + if (_y1 > _y2) { + sgl_swap(&_y1, &_y2); + line->y_swap = 1; + } + else { + line->y_swap = 0; + } + + /* default thinckness is 1 */ + obj->coords.x1 = _x1; + obj->coords.y1 = _y1; + obj->coords.x2 = _x2; + obj->coords.y2 = _y2; + obj->border = 2; + + sgl_obj_set_dirty(obj); +} diff --git a/User/system/sgl/widgets/line/sgl_line.h b/User/system/sgl/widgets/line/sgl_line.h new file mode 100644 index 0000000..32159d8 --- /dev/null +++ b/User/system/sgl/widgets/line/sgl_line.h @@ -0,0 +1,112 @@ +/* source/widgets/sgl_line.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LINE_H__ +#define __SGL_LINE_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl line struct + * @obj: sgl general object + * @color: line color + * @x_swap: x coordinate swap + * @y_swap: y coordinate swap + * @alpha: alpha + */ +typedef struct sgl_line { + sgl_obj_t obj; + sgl_color_t color; + uint8_t x_swap : 4; + uint8_t y_swap : 4; + uint8_t alpha; +}sgl_line_t; + + +/** + * @brief create a line object + * @param parent parent of the line + * @return line object + */ +sgl_obj_t* sgl_line_create(sgl_obj_t* parent); + + +/** + * @brief set line color + * @param obj line object + * @param color line color + * @return none + */ +static inline void sgl_line_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj); + line->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set line alpha + * @param obj line object + * @param alpha line alpha + * @return none + */ +static inline void sgl_line_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + SGL_ASSERT(obj != NULL); + sgl_line_t *line = sgl_container_of(obj, sgl_line_t, obj); + line->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set line start position + * @param obj line object + * @param x start x position + * @param y start y position + * @return none + */ +void sgl_line_set_pos(sgl_obj_t *obj, int16_t x1, int16_t y1, int16_t x2, int16_t y2); + +/** + * @brief set line width + * @param obj line object + * @param width line width + * @return none + */ +static inline void sgl_line_set_width(sgl_obj_t *obj, uint8_t width) +{ + SGL_ASSERT(obj != NULL); + obj->border = width << 1; + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_LINE_H__ diff --git a/User/system/sgl/widgets/listview/sgl_listview.c b/User/system/sgl/widgets/listview/sgl_listview.c new file mode 100644 index 0000000..d0c58d9 --- /dev/null +++ b/User/system/sgl/widgets/listview/sgl_listview.c @@ -0,0 +1,286 @@ +/* source/widgets/sgl_listview.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sgl_listview.h" +#include + + +/** + * @brief set listview object style + * @param obj pointer to the object + * @param type style type + * @param value style value + * @return none + */ +void sgl_listview_set_style(sgl_obj_t *obj, sgl_style_type_t type, size_t value) +{ + sgl_listview_t *listview = (sgl_listview_t*)obj; + + switch((int)type) { + case SGL_STYLE_POS_X: + sgl_obj_set_pos_x(obj, value); + break; + + case SGL_STYLE_POS_Y: + sgl_obj_set_pos_y(obj, value); + break; + + case SGL_STYLE_SIZE_W: + sgl_obj_set_width(obj, value); + break; + + case SGL_STYLE_SIZE_H: + sgl_obj_set_height(obj, value); + break; + + case SGL_STYLE_COLOR: + listview->desc.color = sgl_int2color(value); + break; + + case SGL_STYLE_RADIUS: + listview->desc.radius = value; + break; + + case SGL_STYLE_ALPHA: + listview->desc.alpha = value; + break; + + case SGL_STYLE_BORDER_COLOR: + listview->desc.border_color = sgl_int2color(value); + break; + + case SGL_STYLE_BORDER_WIDTH: + listview->desc.border = value; + break; + + case SGL_STYLE_PIXMAP: + listview->desc.pixmap = (sgl_pixmap_t*)value; + break; + + case SGL_STYLE_FONT: + listview->font = (sgl_font_t*)value; + break; + + default: + SGL_LOG_WARN("sgl_listview_set_style: unsupported style type %d", type); + break; + } + + /* set dirty */ + sgl_obj_set_dirty(obj); +} + + +/** + * @brief get listview object style + * @param obj pointer to the object + * @param type style type + * @return style value + */ +size_t sgl_listview_get_style(sgl_obj_t *obj, sgl_style_type_t type) +{ + sgl_listview_t *listview = (sgl_listview_t*)obj; + + switch((int)type) { + case SGL_STYLE_POS_X: + return sgl_obj_get_pos_x(obj); + + case SGL_STYLE_POS_Y: + return sgl_obj_get_pos_y(obj); + + case SGL_STYLE_SIZE_W: + return sgl_obj_get_width(obj); + + case SGL_STYLE_SIZE_H: + return sgl_obj_get_height(obj); + + case SGL_STYLE_FONT: + return (size_t)listview->font; + + default: + SGL_LOG_WARN("sgl_listview_get_style: unsupported style type %d", type); + break; + } + + return SGL_STYLE_FAILED; +} + + +static void sgl_listview_event_cb(sgl_event_t *event) +{ + sgl_listview_t *listview = (sgl_listview_t*)event->param; + sgl_obj_t *parent = &listview->obj; + sgl_obj_t *child = NULL; + + if(event->type == SGL_EVENT_RELEASED) { + //int diff = item_height + listview->coords_offset; + child = parent->child; + if(listview->coords_offset > 0) { + sgl_obj_for_each_child(child, parent) { + child->coords.y1 -= listview->coords_offset; + child->coords.y2 -= listview->coords_offset; + child->area.y1 -= listview->coords_offset; + child->area.y2 -= listview->coords_offset; + } + listview->coords_offset = 0; + } + // else if(child->coords.y2 < item_height) { + // diff = item_height - child->coords.y2; + // sgl_obj_for_each_child(child, parent) { + // child->coords.y1 += diff; + // child->coords.y2 += diff; + // child->area.y1 += diff; + // child->area.y2 += diff; + // } + // listview->coords_offset = (-diff); + // } + sgl_obj_set_dirty(parent); + } +} + + +static void sgl_listview_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_listview_t *listview = (sgl_listview_t*)obj; + //int coords_end = 0; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &obj->coords, &listview->desc); + } + else if(evt->type == SGL_EVENT_MOVE_UP) { + sgl_listview_set_offset(obj, - evt->distance); + } + else if(evt->type == SGL_EVENT_MOVE_DOWN) { + sgl_listview_set_offset(obj, evt->distance); + } + else if(evt->type == SGL_EVENT_RELEASED) { + + } + + if(obj->event_fn) { + obj->event_fn(evt); + } +} + + +/** + * @brief create listview object + * @param parent pointer to the parent object + * @return pointer to the listview object + */ +sgl_obj_t* sgl_listview_create(sgl_obj_t* parent) +{ + sgl_listview_t *listview = sgl_malloc(sizeof(sgl_listview_t)); + if(listview == NULL) { + SGL_LOG_ERROR("sgl_listview_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(listview, 0, sizeof(sgl_listview_t)); + + sgl_obj_t *obj = &listview->obj; + sgl_obj_init(&listview->obj, parent); + obj->construct_fn = sgl_listview_construct_cb; +#if CONFIG_SGL_USE_STYLE_UNIFIED_API + obj->set_style = sgl_listview_set_style; + obj->get_style = sgl_listview_get_style; +#endif + sgl_obj_set_movable(obj); + + listview->desc.alpha = SGL_ALPHA_MAX; + listview->desc.border = 0; + listview->desc.radius = 0; + listview->font = NULL; + + listview->item_count = 0; + listview->item_height = 23; + listview->item_selected = -1; + + sgl_obj_set_event_cb(obj, sgl_listview_event_cb, (size_t)listview); + + return obj; +} + + +sgl_obj_t* sgl_listview_add_item(sgl_obj_t *listview, sgl_icon_pixmap_t *icon, const char *text) +{ + sgl_listview_t *plistview = (sgl_listview_t *)listview; + + sgl_obj_t *new_obj = sgl_button_create(listview); + new_obj->coords.x1 = listview->coords.x1; + new_obj->coords.x2 = listview->coords.x2; + new_obj->coords.y1 = listview->coords.y1 + plistview->item_count * plistview->item_height; + new_obj->coords.y2 = new_obj->coords.y1 + plistview->item_height; + + sgl_button_set_style(new_obj, SGL_STYLE_TEXT, (size_t)text); + sgl_button_set_style(new_obj, SGL_STYLE_TEXT_COLOR, SGL_COLOR(SGL_COLOR_BLACK)); + sgl_button_set_style(new_obj, SGL_STYLE_ALIGN, SGL_ALIGN_LEFT_MID); + sgl_button_set_style(new_obj, SGL_STYLE_TEXT_X_OFFSET, 10); + if(icon) { + sgl_button_set_style(new_obj, SGL_STYLE_ICON, (size_t)icon); + } + sgl_button_set_style(new_obj, SGL_STYLE_FONT, (size_t)plistview->font); + sgl_button_set_style(new_obj, SGL_STYLE_BORDER_WIDTH, 1); + sgl_button_set_style(new_obj, SGL_STYLE_BORDER_COLOR, SGL_COLOR(SGL_COLOR_BLACK)); + sgl_button_set_style(new_obj, SGL_STYLE_COLOR, SGL_COLOR(SGL_COLOR_BLUE)); + + sgl_obj_set_event_cb(new_obj, sgl_listview_event_cb, (size_t)plistview); + + plistview->item_count ++; + + return new_obj; +} + + +void sgl_listview_set_child_style(sgl_obj_t *listview, sgl_style_type_t type, size_t value) +{ + sgl_obj_t *child = NULL; + + sgl_obj_for_each_child(child, listview) { + sgl_button_set_style(child, type, value); + } +} + + +void sgl_listview_set_offset(sgl_obj_t *listview, int16_t offset) +{ + sgl_listview_t *plistview = (sgl_listview_t *)listview; + plistview->coords_offset += offset; + sgl_obj_t *child = NULL; + + sgl_obj_for_each_child(child, listview) { + child->coords.y1 += offset; + child->coords.y2 += offset; + child->area.y1 += offset; + child->area.y2 += offset; + } +} diff --git a/User/system/sgl/widgets/listview/sgl_listview.h b/User/system/sgl/widgets/listview/sgl_listview.h new file mode 100644 index 0000000..9f97ba1 --- /dev/null +++ b/User/system/sgl/widgets/listview/sgl_listview.h @@ -0,0 +1,88 @@ +/* source/widgets/sgl_listview.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_LISTVIEW_H__ +#define __SGL_LISTVIEW_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl listview + * @obj: sgl general object + * @desc: listview draw description + */ +typedef struct sgl_listview { + sgl_obj_t obj; + sgl_draw_rect_t desc; + sgl_font_t *font; + int16_t item_height; + int16_t item_count; + int16_t item_selected; + int16_t coords_offset; +} sgl_listview_t; + + +/** + * @brief create listview object + * @param parent pointer to the parent object + * @return pointer to the listview object + */ +sgl_obj_t* sgl_listview_create(sgl_obj_t* parent); + + +/** + * @brief set listview object style + * @param obj pointer to the object + * @param type style type + * @param value style value + * @return none + */ +void sgl_listview_set_style(sgl_obj_t *obj, sgl_style_type_t type, size_t value); + + +/** + * @brief get listview object style + * @param obj pointer to the object + * @param type style type + * @return style value + */ +size_t sgl_listview_get_style(sgl_obj_t *obj, sgl_style_type_t type); + + +sgl_obj_t* sgl_listview_add_item(sgl_obj_t *listview, sgl_icon_pixmap_t *icon, const char *text); + + +void sgl_listview_set_child_style(sgl_obj_t *listview, sgl_style_type_t type, size_t value); + + +void sgl_listview_set_offset(sgl_obj_t *listview, int16_t offset); + +#endif // !__SGL_LISTVIEW_H__ diff --git a/User/system/sgl/widgets/lm.cfg b/User/system/sgl/widgets/lm.cfg new file mode 100644 index 0000000..97230e3 --- /dev/null +++ b/User/system/sgl/widgets/lm.cfg @@ -0,0 +1,54 @@ +# source/widgets/lm.cfg +# +# MIT License +# +# Copyright(c) 2023-present All contributors of SGL +# Document reference link: https://sgl-docs.readthedocs.io +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +SRC += line/sgl_line.c +SRC += rectangle/sgl_rectangle.c +SRC += circle/sgl_circle.c +SRC += ring/sgl_ring.c +SRC += arc/sgl_arc.c +SRC += button/sgl_button.c +SRC += slider/sgl_slider.c +SRC += progress/sgl_progress.c +SRC += label/sgl_label.c +SRC += switch/sgl_switch.c +SRC += msgbox/sgl_msgbox.c +SRC += textline/sgl_textline.c +SRC += textbox/sgl_textbox.c +SRC += checkbox/sgl_checkbox.c +# SRC += listview/sgl_listview.c +SRC += icon/sgl_icon.c +SRC += numberkbd/sgl_numberkbd.c +SRC += keyboard/sgl_keyboard.c +SRC += dropdown/sgl_dropdown.c +SRC += led/sgl_led.c +SRC += 2dball/sgl_2dball.c +SRC += unzip_image/sgl_unzip_image.c +SRC += scroll/sgl_scroll.c +SRC += scope/sgl_scope.c +SRC += ext_img/sgl_ext_img.c +SRC += polygon/sgl_polygon.c +SRC += box/sgl_box.c +SRC += canvas/sgl_canvas.c +SRC += bar/sgl_bar.c +SRC += win/sgl_win.c diff --git a/User/system/sgl/widgets/msgbox/sgl_msgbox.c b/User/system/sgl/widgets/msgbox/sgl_msgbox.c new file mode 100644 index 0000000..8a62048 --- /dev/null +++ b/User/system/sgl/widgets/msgbox/sgl_msgbox.c @@ -0,0 +1,233 @@ +/* source/widgets/sgl_msgbox.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "sgl_msgbox.h" +#include + + +static void msgbox_draw_text(sgl_surf_t *surf, sgl_area_t *area, sgl_rect_t *coords, const char *text, const sgl_font_t *font, sgl_color_t color, uint8_t alpha, uint8_t y_offset) +{ + sgl_pos_t align_pos; + align_pos = sgl_get_text_pos(coords, font, text, 0, SGL_ALIGN_CENTER); + sgl_draw_string(surf, area, align_pos.x, align_pos.y + y_offset, text, color, alpha, font); +} + + +static void sgl_msgbox_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + const sgl_font_t *font = msgbox->font; + int32_t font_height = sgl_font_get_height(font) + 8; + int16_t border = msgbox->body_desc.border; + uint8_t title_height = msgbox->title_height ? msgbox->title_height : font_height; // title height + uint8_t msg_y_offset = msgbox->text_y_offset; // message text y coords offset + + SGL_ASSERT(msgbox->font != NULL); + + sgl_color_t tmp_color; + sgl_area_t button_coords = { + .x1 = obj->coords.x1, + .x2 = obj->coords.x2, + .y1 = obj->coords.y2 - font_height, + .y2 = obj->coords.y2 + }; + + sgl_area_t left_coords = { + .x1 = obj->coords.x1 + border, + .x2 = (obj->coords.x1 + obj->coords.x2) / 2 - border / 2, + .y1 = obj->coords.y2 - 2 * font_height, + .y2 = obj->coords.y2 - border, + }; + + sgl_area_t right_coords = { + .x1 = (obj->coords.x1 + obj->coords.x2) / 2 + border / 2, + .x2 = obj->coords.x2 - border, + .y1 = obj->coords.y2 - 2 * font_height, + .y2 = obj->coords.y2 - border, + }; + + sgl_area_t title_coords = { + .x1 = obj->coords.x1 + border + 2, + .x2 = obj->coords.x2 - border + 2, + .y1 = obj->coords.y1 + 1, + .y2 = obj->coords.y1 + title_height + border, + }; + + sgl_area_t text_coords = { + .x1 = obj->coords.x1 + border + 2 + msgbox->text_x_offset, + .x2 = obj->coords.x2 - border - 2, + .y1 = obj->coords.y1 + title_height + border + msg_y_offset, + .y2 = obj->coords.y2 - (font_height + border), + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if(msgbox->status & SGL_MSGBOX_STATUS_EXIT) { + sgl_obj_set_destroyed(&msgbox->obj); + } + + sgl_draw_rect(surf, &obj->area, &obj->coords, &msgbox->body_desc); + + msgbox_draw_text(surf, &obj->area, &title_coords, msgbox->title_text, font, msgbox->title_color, msgbox->body_desc.alpha, 0); + + sgl_draw_fill_hline(surf, &obj->area, + obj->coords.y1 + title_height + 4, + obj->coords.x1 + msgbox->body_desc.border, + obj->coords.x2 - msgbox->body_desc.border, + msgbox->body_desc.border, + msgbox->body_desc.border_color, + msgbox->body_desc.alpha + ); + + sgl_draw_string_mult_line(surf, &text_coords, text_coords.x1, text_coords.y1, msgbox->msg_text, msgbox->msg_color, msgbox->body_desc.alpha, font, msgbox->msg_line_margin); + + if(msgbox->status & SGL_MSGBOX_STATUS_LEFT) { + tmp_color = msgbox->lbtn_color; + msgbox->lbtn_color = sgl_color_mixer(msgbox->lbtn_text_color, msgbox->body_desc.color, 128); + } + else if(msgbox->status & SGL_MSGBOX_STATUS_RIGHT) { + tmp_color = msgbox->rbtn_color; + msgbox->rbtn_color = sgl_color_mixer(msgbox->rbtn_text_color, msgbox->body_desc.color, 128); + } + + sgl_draw_fill_rect(surf, &button_coords, &left_coords, obj->radius, msgbox->lbtn_color, msgbox->body_desc.alpha); + sgl_draw_fill_rect(surf, &button_coords, &right_coords, obj->radius, msgbox->rbtn_color, msgbox->body_desc.alpha); + msgbox_draw_text(surf, &obj->area, &left_coords, msgbox->lbtn_text, font, msgbox->lbtn_text_color, msgbox->body_desc.alpha, font_height / 2); + msgbox_draw_text(surf, &obj->area, &right_coords, msgbox->rbtn_text, font, msgbox->rbtn_text_color, msgbox->body_desc.alpha, font_height / 2); + + if(msgbox->status & SGL_MSGBOX_STATUS_LEFT) { + msgbox->lbtn_color = tmp_color; + } + else if(msgbox->status & SGL_MSGBOX_STATUS_RIGHT) { + msgbox->rbtn_color = tmp_color; + } + } + else if(evt->type == SGL_EVENT_PRESSED) { + if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x < ((obj->coords.x1 + obj->coords.x2) / 2)) { + msgbox->status |= SGL_MSGBOX_STATUS_LEFT; + if (msgbox->exit_btn) { + *msgbox->exit_btn = msgbox->lbtn_text; + } + sgl_obj_update_area(&left_coords); + } + else if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x > ((obj->coords.x1 + obj->coords.x2) / 2)) { + msgbox->status |= SGL_MSGBOX_STATUS_RIGHT; + if (msgbox->exit_btn) { + *msgbox->exit_btn = msgbox->rbtn_text; + } + sgl_obj_update_area(&right_coords); + } + else { + sgl_obj_clear_dirty(obj); + return; + } + } + else if(evt->type == SGL_EVENT_RELEASED) { + if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x < ((obj->coords.x1 + obj->coords.x2) / 2)) { + msgbox->status |= SGL_MSGBOX_STATUS_EXIT; + sgl_obj_set_destroyed(obj); + } + else if(evt->pos.y > (obj->coords.y2 - font_height - 2) && evt->pos.x > ((obj->coords.x1 + obj->coords.x2) / 2)) { + msgbox->status |= SGL_MSGBOX_STATUS_EXIT; + sgl_obj_set_destroyed(obj); + } + else { + sgl_obj_clear_dirty(obj); + return; + } + } + else if (evt->type == SGL_EVENT_OPTION_WALK) { + if (msgbox->status == SGL_MSGBOX_STATUS_NORMAL) { + msgbox->status = SGL_MSGBOX_STATUS_LEFT; + } + else if (msgbox->status == SGL_MSGBOX_STATUS_LEFT) { + msgbox->status = SGL_MSGBOX_STATUS_RIGHT; + if (msgbox->exit_btn) { + *msgbox->exit_btn = msgbox->rbtn_text; + } + } + else if (msgbox->status == SGL_MSGBOX_STATUS_RIGHT) { + msgbox->status = SGL_MSGBOX_STATUS_LEFT; + if (msgbox->exit_btn) { + *msgbox->exit_btn = msgbox->lbtn_text; + } + } + sgl_obj_update_area(&button_coords); + } + else if (evt->type == SGL_EVENT_OPTION_TAP) { + sgl_obj_set_destroyed(obj); + } +} + + +/** + * @brief create a message box object + * @param parent parent of the message box + * @return message box object + */ +sgl_obj_t* sgl_msgbox_create(sgl_obj_t* parent) +{ + sgl_msgbox_t *msgbox = sgl_malloc(sizeof(sgl_msgbox_t)); + if(msgbox == NULL) { + SGL_LOG_ERROR("sgl_msgbox_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(msgbox, 0, sizeof(sgl_msgbox_t)); + + sgl_obj_t *obj = &msgbox->obj; + sgl_obj_init(&msgbox->obj, parent); + obj->construct_fn = sgl_msgbox_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + msgbox->body_desc.alpha = SGL_THEME_ALPHA; + msgbox->body_desc.color = SGL_THEME_COLOR; + msgbox->body_desc.radius = SGL_THEME_RADIUS; + msgbox->body_desc.border = SGL_THEME_BORDER_WIDTH; + msgbox->body_desc.border_color = SGL_THEME_BORDER_COLOR; + msgbox->body_desc.pixmap = NULL; + + msgbox->font = sgl_get_system_font(); + msgbox->msg_color = SGL_THEME_TEXT_COLOR; + msgbox->title_text = "Message Box"; + msgbox->msg_line_margin = 1; + msgbox->msg_text = "NULL"; + + msgbox->lbtn_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_TEXT_COLOR, 200); + msgbox->rbtn_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_TEXT_COLOR, 200); + msgbox->lbtn_text = "YES"; + msgbox->rbtn_text = "NO"; + msgbox->lbtn_text_color = SGL_THEME_TEXT_COLOR; + msgbox->rbtn_text_color = SGL_THEME_TEXT_COLOR; + + msgbox->status = SGL_MSGBOX_STATUS_NORMAL; + msgbox->title_height = 0; + msgbox->text_y_offset = 0; + msgbox->text_x_offset = 0; + msgbox->exit_btn = NULL; + + sgl_obj_set_clickable(obj); + + return obj; +} diff --git a/User/system/sgl/widgets/msgbox/sgl_msgbox.h b/User/system/sgl/widgets/msgbox/sgl_msgbox.h new file mode 100644 index 0000000..2367fcc --- /dev/null +++ b/User/system/sgl/widgets/msgbox/sgl_msgbox.h @@ -0,0 +1,378 @@ +/* source/widgets/sgl_msgbox.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_MSGBOX_H__ +#define __SGL_MSGBOX_H__ + +#include +#include +#include +#include +#include +#include +#include + + +#define SGL_MSGBOX_STATUS_NORMAL (1 << 7) +#define SGL_MSGBOX_STATUS_LEFT (1 << 0) +#define SGL_MSGBOX_STATUS_RIGHT (1 << 1) +#define SGL_MSGBOX_STATUS_EXIT (1 << 2) + +/** + * @brief sgl message box struct + * @obj: sgl general object + * @body_desc: pointer to sgl_draw_rect_t descriptor + */ +typedef struct sgl_msgbox { + sgl_obj_t obj; + sgl_draw_rect_t body_desc; + const sgl_font_t *font; + + const char *title_text; + const char *msg_text; + sgl_color_t title_color; + sgl_color_t msg_color; + uint8_t msg_line_margin; + uint8_t status; + sgl_color_t lbtn_text_color; + sgl_color_t rbtn_text_color; + sgl_color_t lbtn_color; + sgl_color_t rbtn_color; + const char *lbtn_text; + const char *rbtn_text; + + uint8_t title_height; + uint8_t text_y_offset; + uint8_t text_x_offset; + const char **exit_btn; +}sgl_msgbox_t; + + +/** + * @brief create a message box object + * @param parent parent of the message box + * @return message box object + */ +sgl_obj_t* sgl_msgbox_create(sgl_obj_t* parent); + +/** + * @brief set message box color + * @param obj message box object + * @param color message box color + * @return none + */ +static inline void sgl_msgbox_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box alpha + * @param obj message box object + * @param alpha message box alpha + * @return none + */ +static inline void sgl_msgbox_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box radius + * @param obj message box object + * @param radius message box radius + * @return none + */ +static inline void sgl_msgbox_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.radius = radius; + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box border width + * @param obj message box object + * @param width message box border width + * @return none + */ +static inline void sgl_msgbox_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box border color + * @param obj message box object + * @param color message box border color + * @return none + */ +static inline void sgl_msgbox_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box pixmap + * @param obj message box object + * @param pixmap message box pixmap + * @return none + */ +static inline void sgl_msgbox_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->body_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box all text font + * @param obj message box object + * @param font message box font + * @return none + */ +static inline void sgl_msgbox_set_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box title text + * @param obj message box object + * @param text message box title text + * @return none + */ +static inline void sgl_msgbox_set_title_text(sgl_obj_t *obj, const char *text) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->title_text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box title text color + * @param obj message box object + * @param color message box title text color + * @return none + */ +static inline void sgl_msgbox_set_title_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->title_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box message text + * @param obj message box object + * @param text message box message text + * @return none + */ +static inline void sgl_msgbox_set_msg_text(sgl_obj_t *obj, const char *text) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->msg_text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box message text color + * @param obj message box object + * @param color message box message text color + * @return none + */ +static inline void sgl_msgbox_set_msg_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->msg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box message text line margin + * @param obj message box object + * @param margin message box message text line margin + * @return none + */ +static inline void sgl_msgbox_set_msg_line_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->msg_line_margin = margin; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box left button text + * @param obj message box object + * @param text message box left button text + * @return none + */ +static inline void sgl_msgbox_set_left_btn_text(sgl_obj_t *obj, const char *text) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->lbtn_text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box left button text color + * @param obj message box object + * @param color message box left button text color + * @return none + */ +static inline void sgl_msgbox_set_left_btn_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->lbtn_text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box left button color + * @param obj message box object + * @param color message box left button color + * @return none + */ +static inline void sgl_msgbox_set_left_btn_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->lbtn_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box right button text + * @param obj message box object + * @param text message box right button text + * @return none + */ +static inline void sgl_msgbox_set_right_btn_text(sgl_obj_t *obj, const char *text) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->rbtn_text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box right button text color + * @param obj message box object + * @param color message box right button text color + * @return none + */ +static inline void sgl_msgbox_set_right_btn_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->rbtn_text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box right button color + * @param obj message box object + * @param color message box right button color + * @return none + */ +static inline void sgl_msgbox_set_right_btn_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->rbtn_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box exit answer + * @param obj message box object + * @param answer [out] pointer to exit answer + * @return none + * @note the answer will point to the answer btn string when the message box is destroyed + */ +static inline void sgl_msgbox_set_exit_answer(sgl_obj_t *obj, const char **answer) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->exit_btn = answer; +} + +/** + * @brief get message box current button text + * @param obj message box object + * @return current current button text + */ +static inline const char* sgl_msgbox_get_current_btn(sgl_obj_t *obj) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + return msgbox->status & SGL_MSGBOX_STATUS_LEFT ? msgbox->lbtn_text : msgbox->rbtn_text; +} + +/** + * @brief set message box title height + * @param obj message box object + * @param height title bar height in pixels + * @return none + */ +static inline void sgl_msgbox_set_title_height(sgl_obj_t *obj, uint8_t height) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->title_height = height; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box message text x offset + * @param obj message box object + * @param offset x axis offset for message text + * @return none + */ +static inline void sgl_msgbox_set_msg_x_offset(sgl_obj_t *obj, uint8_t offset) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->text_x_offset = offset; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set message box message text y offset + * @param obj message box object + * @param offset y axis offset for message text + * @return none + */ +static inline void sgl_msgbox_set_msg_y_offset(sgl_obj_t *obj, uint8_t offset) +{ + sgl_msgbox_t *msgbox = sgl_container_of(obj, sgl_msgbox_t, obj); + msgbox->text_y_offset = offset; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_MSGBOX_H__ diff --git a/User/system/sgl/widgets/numberkbd/sgl_numberkbd.c b/User/system/sgl/widgets/numberkbd/sgl_numberkbd.c new file mode 100644 index 0000000..edb32b5 --- /dev/null +++ b/User/system/sgl/widgets/numberkbd/sgl_numberkbd.c @@ -0,0 +1,277 @@ +/* source/widgets/sgl_numberkbd.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_numberkbd.h" + + +#define NUMBERKBD_BTN_ROW 5 +#define NUMBERKBD_BTN_COL 4 + +#define NUMBERKBD_BTN_OK_ASCII 13 + +static const char kbd_digits[NUMBERKBD_BTN_ROW][NUMBERKBD_BTN_COL] = { + {'+', '-', '*', '/' }, + {'7', '8', '9', '=' }, + {'4', '5', '6', '\b' }, + {'1', '2', '3', NUMBERKBD_BTN_OK_ASCII }, + {'.', '0', '%', NUMBERKBD_BTN_OK_ASCII } +}; + + +static const uint8_t btn_enter_bitmap[] = { + /*  */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0xfa,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xef,0xff,0xa0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0xff,0xff,0xfa,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xef,0xff,0xff,0xfe,0x50, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8e,0xff,0xff,0xff,0xfe,0x30, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xef,0xff,0xff,0xff,0xe3,0x00, + 0x00,0x00,0xae,0xe8,0x00,0x00,0x00,0x00,0x8e,0xff,0xff,0xff,0xfe,0x30,0x00, + 0x00,0x0a,0xff,0xfe,0x80,0x00,0x00,0x08,0xef,0xff,0xff,0xff,0xe3,0x00,0x00, + 0x00,0xae,0xff,0xff,0xe8,0x00,0x00,0x8e,0xff,0xff,0xff,0xfe,0x30,0x00,0x00, + 0x05,0xef,0xff,0xff,0xfe,0x80,0x08,0xef,0xff,0xff,0xff,0xe3,0x00,0x00,0x00, + 0x03,0xef,0xff,0xff,0xff,0xe8,0x8e,0xff,0xff,0xff,0xfe,0x30,0x00,0x00,0x00, + 0x00,0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x00,0x00,0x00,0x00, + 0x00,0x05,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x30,0x00,0x00,0x00,0x00, + 0x00,0x00,0x5e,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x05,0xef,0xff,0xff,0xff,0xff,0xfe,0x30,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x5e,0xff,0xff,0xff,0xff,0xe3,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x05,0xef,0xff,0xff,0xfe,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5e,0xff,0xff,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x05,0xef,0xfe,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x5c,0xc3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + + +static sgl_icon_pixmap_t enter_icon = { + .bitmap = btn_enter_bitmap, + .height = 20, + .width = 30, +}; + + +static const uint8_t btn_backspace_bitmap[] = { + /*  */ + 0x00,0x00,0x00,0x3e,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x05,0xef,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x5e,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0xef,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x8e,0xff,0xff,0xec,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc, + 0x0a,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, + 0x3e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, + 0x03,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, + 0x00,0x3e,0xff,0xff,0xc6,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x65, + 0x00,0x03,0xef,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0c,0xff,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xcf,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0a,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + + +static sgl_icon_pixmap_t backspace_icon = { + .bitmap = btn_backspace_bitmap, + .height = 13, + .width = 30, +}; + + +/** + * @brief numberkbd constructor function + * @param surf: pointer to surface + * @param obj: pointer to numberkbd object + * @param evt: pointer to event + * @return none + */ +static void sgl_numberkbd_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + int16_t body_w = obj->coords.x2 - obj->coords.x1 + 1; + int16_t body_h = obj->coords.y2 - obj->coords.y1 + 1; + sgl_color_t btn_color = numberkbd->btn_desc.color; + + int16_t box_w = (body_w - (NUMBERKBD_BTN_COL + 1) * numberkbd->margin) / NUMBERKBD_BTN_COL; + int16_t box_h = (body_h - (NUMBERKBD_BTN_ROW + 1) * numberkbd->margin) / NUMBERKBD_BTN_ROW; + int16_t text_x = 0, text_y = 0, btn_row = 0, btn_col = 0; + + sgl_rect_t btn = { + .y1 = obj->coords.y1 + numberkbd->margin, + .x2 = obj->coords.x1 + numberkbd->margin + box_w, + .y2 = obj->coords.y1 + numberkbd->margin + box_h, + }; + + SGL_ASSERT(numberkbd->font != NULL); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &obj->coords, &numberkbd->body_desc); + + for(; btn.y1 < (obj->coords.y2 - numberkbd->margin); btn.y1 += (box_h + numberkbd->margin), btn.y2 = (btn.y1 + box_h)) { + btn.x1 = obj->coords.x1 + numberkbd->margin; + text_y = btn.y1 + ((box_h - sgl_font_get_height(numberkbd->font)) / 2); + btn_col = 0; + + for(btn.x2 = (btn.x1 + box_w); btn.x1 < (obj->coords.x2 - numberkbd->margin) ; btn.x1 += (box_w + numberkbd->margin), btn.x2 = (btn.x1 + box_w)) { + if(numberkbd->opcode != kbd_digits[btn_row][btn_col]) { + numberkbd->btn_desc.color = btn_color; + } + else { + numberkbd->btn_desc.color = sgl_color_mixer(btn_color, numberkbd->text_color, 128); + } + + if(btn_col == 3 && btn_row > 1) { + if(btn_row == 2) { + sgl_draw_rect(surf, &btn, &btn, &numberkbd->btn_desc); + text_x = btn.x1 + ((box_w - backspace_icon.width) / 2); + text_y = btn.y1 + ((box_h - backspace_icon.height + 1) / 2); + sgl_draw_icon(surf, &btn, text_x, text_y, numberkbd->text_color, numberkbd->btn_desc.alpha, &backspace_icon); + } + else if (btn_row == 3) { + btn.y2 += (numberkbd->margin + box_h); + sgl_draw_rect(surf, &btn, &btn, &numberkbd->btn_desc); + text_x = btn.x1 + ((box_w - enter_icon.width) / 2); + text_y = btn.y1 + ((2 * box_h - enter_icon.height) / 2); + sgl_draw_icon(surf, &btn, text_x, text_y, numberkbd->text_color, numberkbd->btn_desc.alpha, &enter_icon); + } + } + else { + sgl_draw_rect(surf, &btn, &btn, &numberkbd->btn_desc); + text_x = btn.x1 + ((box_w - sgl_font_get_string_width("0", numberkbd->font)) / 2); + sgl_draw_character(surf, &obj->area, text_x, text_y, kbd_digits[btn_row][btn_col] - 32, numberkbd->text_color, numberkbd->btn_desc.alpha, numberkbd->font); + } + btn_col ++; + } + + numberkbd->btn_desc.color = btn_color; + btn_row ++; + } + } + else if(evt->type == SGL_EVENT_PRESSED) { + int16_t x_rel = evt->pos.x - obj->coords.x1; + int16_t y_rel = evt->pos.y - obj->coords.y1; + + btn_col = -1; + int16_t cur_x = numberkbd->margin; + for (int c = 0; c < NUMBERKBD_BTN_COL; c++) { + if (x_rel >= cur_x && x_rel < cur_x + box_w) { + btn_col = c; + break; + } + cur_x += box_w + numberkbd->margin; + } + + btn_row = -1; + int16_t cur_y = numberkbd->margin; + + for (int r = 0; r < NUMBERKBD_BTN_ROW; r++) { + if (y_rel >= cur_y && y_rel < cur_y + box_h) { + btn_row = r; + break; + } + cur_y += box_h + numberkbd->margin; + } + + if(btn_col == 3 && btn_row >= 3) { + numberkbd->opcode = NUMBERKBD_BTN_OK_ASCII; + } + else if (btn_col >= 0 && btn_row >= 0) { + numberkbd->opcode = (uint8_t)kbd_digits[btn_row][btn_col]; + } + else { + return; + } + + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + if(numberkbd->opcode == 0) { + sgl_obj_clear_dirty(obj); + return; + } + numberkbd->opcode = 0; + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_DRAW_INIT) { + int16_t new_width = box_w * NUMBERKBD_BTN_COL + (NUMBERKBD_BTN_COL + 1) * numberkbd->margin; + int16_t new_height = box_h * NUMBERKBD_BTN_ROW + (NUMBERKBD_BTN_ROW + 1) * numberkbd->margin; + + obj->coords.x2 = obj->coords.x1 + new_width; + obj->coords.y2 = obj->coords.y1 + new_height; + + SGL_ASSERT(numberkbd->font != NULL); + } +} + + +/** + * @brief create numberkbd object + * @param parent parent of object + * @return numberkbd object + */ +sgl_obj_t* sgl_numberkbd_create(sgl_obj_t* parent) +{ + sgl_numberkbd_t *numberkbd = sgl_malloc(sizeof(sgl_numberkbd_t)); + if(numberkbd == NULL) { + SGL_LOG_ERROR("sgl_numberkbd_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(numberkbd, 0, sizeof(sgl_numberkbd_t)); + + sgl_obj_t *obj = &numberkbd->obj; + sgl_obj_init(&numberkbd->obj, parent); + obj->construct_fn = sgl_numberkbd_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + obj->clickable = 1; + obj->needinit = 1; + + numberkbd->body_desc.alpha = SGL_THEME_ALPHA; + numberkbd->body_desc.color = SGL_THEME_COLOR; + numberkbd->body_desc.radius = SGL_THEME_RADIUS; + numberkbd->body_desc.border = SGL_THEME_BORDER_WIDTH; + numberkbd->body_desc.border_color = SGL_THEME_BORDER_COLOR; + numberkbd->body_desc.pixmap = NULL; + numberkbd->margin = 5; + numberkbd->text_color = SGL_THEME_TEXT_COLOR; + + numberkbd->btn_desc.alpha = SGL_THEME_ALPHA; + numberkbd->btn_desc.color = SGL_THEME_COLOR; + numberkbd->btn_desc.radius = SGL_THEME_RADIUS; + numberkbd->btn_desc.border = 1; + numberkbd->btn_desc.border_color = SGL_THEME_BORDER_COLOR; + numberkbd->btn_desc.pixmap = NULL; + + numberkbd->font = sgl_get_system_font(); + + return obj; +} diff --git a/User/system/sgl/widgets/numberkbd/sgl_numberkbd.h b/User/system/sgl/widgets/numberkbd/sgl_numberkbd.h new file mode 100644 index 0000000..d80329a --- /dev/null +++ b/User/system/sgl/widgets/numberkbd/sgl_numberkbd.h @@ -0,0 +1,259 @@ +/* source/widgets/sgl_numberkbd.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_NUMBERKBD_H__ +#define __SGL_NUMBERKBD_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl number keyboard struct + * @obj: sgl general object + * @body_desc: pointer to sgl_draw_rect_t descriptor + */ +typedef struct sgl_numberkbd { + sgl_obj_t obj; + sgl_draw_rect_t body_desc; + sgl_draw_rect_t btn_desc; + const sgl_font_t *font; + sgl_color_t text_color; + uint8_t margin; + uint8_t opcode; +}sgl_numberkbd_t; + + +/** + * @brief create numberkbd object + * @param parent parent of object + * @return numberkbd object + */ +sgl_obj_t* sgl_numberkbd_create(sgl_obj_t* parent); + + +/** + * @brief set numberkbd color + * @param obj numberkbd object + * @param color color + * @return none + */ +static inline void sgl_numberkbd_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd alpha + * @param obj numberkbd object + * @param alpha alpha [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->body_desc.alpha = alpha; + numberkbd->btn_desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd radius + * @param obj numberkbd object + * @param radius radius [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + sgl_obj_set_radius(obj, radius); + numberkbd->body_desc.radius = obj->radius; + numberkbd->btn_desc.radius = numberkbd->body_desc.radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd border width + * @param obj numberkbd object + * @param width border width [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->body_desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd border color + * @param obj numberkbd object + * @param color border color + * @return none + */ +static inline void sgl_numberkbd_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->body_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd text font + * @param obj numberkbd object + * @param font font + * @return none + */ +static inline void sgl_numberkbd_set_text_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd text color + * @param obj numberkbd object + * @param color text color + * @return none + */ +static inline void sgl_numberkbd_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd pixmap + * @param obj numberkbd object + * @param pixmap pixmap of numberkbd + * @return none + */ +static inline void sgl_numberkbd_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->btn_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button margin + * @param obj numberkbd object + * @param margin margin [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_btn_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->margin = margin; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button color + * @param obj numberkbd object + * @param color button color + * @return none + */ +static inline void sgl_numberkbd_set_btn_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->btn_desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button border width + * @param obj numberkbd object + * @param width button border width [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_btn_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->btn_desc.border = width; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button border color + * @param obj numberkbd object + * @param color button border color + * @return none + */ +static inline void sgl_numberkbd_set_btn_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->btn_desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button radius + * @param obj numberkbd object + * @param radius button radius [0 ~ 255] + * @return none + */ +static inline void sgl_numberkbd_set_btn_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + sgl_obj_set_radius(obj, radius); + numberkbd->btn_desc.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set numberkbd button pixmap + * @param obj numberkbd object + * @param pixmap button pixmap + * @return none + */ +static inline void sgl_numberkbd_set_btn_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_numberkbd_t *numberkbd = sgl_container_of(obj, sgl_numberkbd_t, obj); + numberkbd->btn_desc.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get numberkbd opcode + * @param obj numberkbd object + * @return opcode [0 ~ 255] + */ +static inline uint8_t sgl_numberkbd_get_opcode(sgl_obj_t *obj) +{ + return ((sgl_numberkbd_t*)obj)->opcode; +} + + +#endif // !__SGL_NUMBERKBD_H__ diff --git a/User/system/sgl/widgets/polygon/sgl_polygon.c b/User/system/sgl/widgets/polygon/sgl_polygon.c new file mode 100644 index 0000000..df228ad --- /dev/null +++ b/User/system/sgl/widgets/polygon/sgl_polygon.c @@ -0,0 +1,379 @@ +/* source/widgets/polygon/sgl_polygon.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "sgl_polygon.h" + + +// Polygon construction callback function +static void sgl_polygon_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_polygon_t *polygon = (sgl_polygon_t*)obj; + + if (evt->type != SGL_EVENT_DRAW_MAIN) { + return; + } + + if (polygon->vertex_count < 3 || polygon->vertices == NULL) { + return; // At least 3 vertices are required to form a polygon + } + + // Draw fill + if (polygon->fill_color.full != 0) { + // Calculate bounding box of polygon (using actual coordinates) + int16_t min_x = polygon->vertices[0].x, max_x = polygon->vertices[0].x; + int16_t min_y = polygon->vertices[0].y, max_y = polygon->vertices[0].y; + + for (uint16_t i = 1; i < polygon->vertex_count; i++) { + sgl_pos_t vertex = polygon->vertices[i]; + min_x = sgl_min(min_x, vertex.x); + max_x = sgl_max(max_x, vertex.x); + min_y = sgl_min(min_y, vertex.y); + max_y = sgl_max(max_y, vertex.y); + } + + // Adjust coordinates relative to parent object + sgl_area_t polygon_area = { + .x1 = min_x + obj->parent->coords.x1, // Adjust to parent coordinates + .x2 = max_x + obj->parent->coords.x1, + .y1 = min_y + obj->parent->coords.y1, + .y2 = max_y + obj->parent->coords.y1 + }; + + sgl_area_t clip; + if (sgl_surf_clip(surf, &polygon_area, &clip) && sgl_area_selfclip(&clip, &obj->area)) { + // Calculate intersections of scan lines with polygon + int intersections[64]; // Assume max 64 intersections per scan line + + for (int y = clip.y1; y <= clip.y2; y++) { + uint8_t count = 0; + + // Calculate intersections of scan line with polygon + for (uint16_t i = 0; i < polygon->vertex_count; i++) { + // Adjust vertex coordinates relative to parent + sgl_pos_t p1 = {polygon->vertices[i].x + obj->parent->coords.x1, + polygon->vertices[i].y + obj->parent->coords.y1}; + sgl_pos_t p2 = {polygon->vertices[(i + 1) % polygon->vertex_count].x + obj->parent->coords.x1, + polygon->vertices[(i + 1) % polygon->vertex_count].y + obj->parent->coords.y1}; + + // Calculate intersection of scan line with edge + if ((p1.y > y) != (p2.y > y)) { + intersections[count++] = p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y); + } + } + + // Sort intersections (using optimized bubble sort) + for (uint8_t i = 0; i < count - 1; i++) { + bool swapped = false; + for (uint8_t j = 0; j < count - i - 1; j++) { + if (intersections[j] > intersections[j + 1]) { + int temp = intersections[j]; + intersections[j] = intersections[j + 1]; + intersections[j + 1] = temp; + swapped = true; + } + } + if (!swapped) break; // If no swaps occurred, sorting is complete + } + + // Fill scan line segments + sgl_color_t *buf = sgl_surf_get_buf(surf, clip.x1 - surf->x1, y - surf->y1); + for (uint8_t i = 0; i < count; i += 2) { + int start = sgl_max(intersections[i], clip.x1); + int end = sgl_min(intersections[i + 1], clip.x2); + + if (start <= end) { + if (polygon->alpha == SGL_ALPHA_MAX) { + for (int x = start; x <= end; x++) { + buf[x - clip.x1] = polygon->fill_color; + } + } else { + for (int x = start; x <= end; x++) { + int buf_index = x - clip.x1; + buf[buf_index] = sgl_color_mixer(polygon->fill_color, buf[buf_index], polygon->alpha); + } + } + } + } + } + } + } + + // Draw border + if (polygon->border_width > 0 && polygon->border_color.full != 0) { + for (uint16_t i = 0; i < polygon->vertex_count; i++) { + // Adjust vertex coordinates relative to parent + sgl_pos_t start = {polygon->vertices[i].x + obj->parent->coords.x1, + polygon->vertices[i].y + obj->parent->coords.y1}; + sgl_pos_t end = {polygon->vertices[(i + 1) % polygon->vertex_count].x + obj->parent->coords.x1, + polygon->vertices[(i + 1) % polygon->vertex_count].y + obj->parent->coords.y1}; + + draw_line_fill_slanted(surf, &obj->area, start.x, start.y, end.x, end.y, polygon->border_width, polygon->border_color, polygon->alpha); + } + } + + // Draw text + if (polygon->text && polygon->font) { + // Calculate center point of polygon + int32_t center_x = 0, center_y = 0; + for (uint16_t i = 0; i < polygon->vertex_count; i++) { + center_x += polygon->vertices[i].x + obj->parent->coords.x1; // Adjust to parent coordinates + center_y += polygon->vertices[i].y + obj->parent->coords.y1; + } + center_x /= polygon->vertex_count; + center_y /= polygon->vertex_count; + + // Calculate text dimensions + int16_t text_width = sgl_font_get_string_width(polygon->text, polygon->font); + int16_t text_height = sgl_font_get_height(polygon->font); + + // Text drawing position (centered) + int16_t text_x = center_x - text_width / 2; + int16_t text_y = center_y - text_height / 2; + + sgl_draw_string(surf, &obj->area, text_x, text_y, polygon->text, polygon->text_color, polygon->alpha, polygon->font); + } +} +// Create polygon object +sgl_obj_t* sgl_polygon_create(sgl_obj_t* parent) +{ + sgl_polygon_t *polygon = (sgl_polygon_t*)sgl_malloc(sizeof(sgl_polygon_t)); + if (polygon == NULL) { + return NULL; + } + + memset(polygon, 0, sizeof(sgl_polygon_t)); + + sgl_obj_t *obj = &polygon->obj; + sgl_obj_init(obj, parent); + obj->construct_fn = sgl_polygon_construct_cb; + + // Set default values + polygon->vertex_count = 0; + polygon->vertices = NULL; + polygon->fill_color = sgl_rgb(127, 127, 127); + polygon->border_color = sgl_rgb(0, 0, 0); + polygon->border_width = 1; + polygon->alpha = SGL_ALPHA_MAX; + polygon->pixmap = NULL; + polygon->text = NULL; + polygon->font = NULL; + polygon->text_color = sgl_rgb(0, 0, 0); + + return obj; +} + +// Set polygon vertices +void sgl_polygon_set_vertices(sgl_obj_t* obj, sgl_pos_t* vertices, uint16_t count) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL || vertices == NULL || count < 3) { + return; + } + + // Free old vertex data (if any) + if (polygon->vertices != NULL) { + sgl_free(polygon->vertices); + } + + // Allocate new vertex data + polygon->vertices = (sgl_pos_t*)sgl_malloc(sizeof(sgl_pos_t) * count); + if (polygon->vertices == NULL) { + polygon->vertex_count = 0; + return; + } + + // Copy vertex data + memcpy(polygon->vertices, vertices, sizeof(sgl_pos_t) * count); + polygon->vertex_count = count; + + // Mark object as needing redraw + sgl_obj_set_dirty(obj); +} + +// Set polygon vertices by coordinate arrays +void sgl_polygon_set_vertex_coords(sgl_obj_t* obj, int16_t* x_coords, int16_t* y_coords, uint16_t count) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL || x_coords == NULL || y_coords == NULL || count < 3) { + return; + } + + // Free old vertex data (if any) + if (polygon->vertices != NULL) { + sgl_free(polygon->vertices); + } + + // Allocate new vertex data + polygon->vertices = (sgl_pos_t*)sgl_malloc(sizeof(sgl_pos_t) * count); + if (polygon->vertices == NULL) { + polygon->vertex_count = 0; + return; + } + + // Build vertices from coordinate arrays + for (uint16_t i = 0; i < count; i++) { + polygon->vertices[i].x = x_coords[i]; + polygon->vertices[i].y = y_coords[i]; + } + polygon->vertex_count = count; + + // Mark object as needing redraw + sgl_obj_set_dirty(obj); +} + +// Set polygon vertices by 2D coordinate array +void sgl_polygon_set_vertex_array(sgl_obj_t* obj, int16_t (*coords)[2], uint16_t count) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL || coords == NULL || count < 3) { + return; + } + + // Free old vertex data (if any) + if (polygon->vertices != NULL) { + sgl_free(polygon->vertices); + } + + // Allocate new vertex data + polygon->vertices = (sgl_pos_t*)sgl_malloc(sizeof(sgl_pos_t) * count); + if (polygon->vertices == NULL) { + polygon->vertex_count = 0; + return; + } + + // Build vertices from 2D coordinate array + for (uint16_t i = 0; i < count; i++) { + polygon->vertices[i].x = coords[i][0]; + polygon->vertices[i].y = coords[i][1]; + } + polygon->vertex_count = count; + + // Mark object as needing redraw + sgl_obj_set_dirty(obj); +} + +// Set fill color +void sgl_polygon_set_fill_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->fill_color = color; + sgl_obj_set_dirty(obj); +} + +// Set border color +void sgl_polygon_set_border_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->border_color = color; + sgl_obj_set_dirty(obj); +} + +// Set border width +void sgl_polygon_set_border_width(sgl_obj_t* obj, uint8_t width) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->border_width = width; + sgl_obj_set_dirty(obj); +} + +// Set alpha value +void sgl_polygon_set_alpha(sgl_obj_t* obj, uint8_t alpha) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +// Set background image +void sgl_polygon_set_pixmap(sgl_obj_t* obj, const sgl_pixmap_t* pixmap) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +// Set text +void sgl_polygon_set_text(sgl_obj_t* obj, const char* text) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->text = text; + sgl_obj_set_dirty(obj); +} + +// Set font +void sgl_polygon_set_font(sgl_obj_t* obj, const sgl_font_t* font) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->font = font; + sgl_obj_set_dirty(obj); +} + +// Set text color +void sgl_polygon_set_text_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_polygon_t *polygon = (sgl_polygon_t *)obj; + if (polygon == NULL) { + return; + } + + polygon->text_color = color; + sgl_obj_set_dirty(obj); +} + + + + + + + + + + diff --git a/User/system/sgl/widgets/polygon/sgl_polygon.h b/User/system/sgl/widgets/polygon/sgl_polygon.h new file mode 100644 index 0000000..402a0ce --- /dev/null +++ b/User/system/sgl/widgets/polygon/sgl_polygon.h @@ -0,0 +1,166 @@ +/* source/widgets/polygon/sgl_polygon.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_POLYGON_H__ +#define __SGL_POLYGON_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief sgl polygon struct + */ + + typedef struct + { + sgl_obj_t obj; // Base object + uint16_t vertex_count; // Number of vertices + sgl_pos_t *vertices; // Array of vertex coordinates + sgl_color_t fill_color; // Fill color + sgl_color_t border_color; // Border color + uint8_t border_width; // Border width + uint8_t alpha; // Alpha value + const sgl_pixmap_t *pixmap; // Background image + const char *text; // Display text + const sgl_font_t *font; // Font + sgl_color_t text_color; // Text color + } sgl_polygon_t; + + /** + * @brief create a polygon object + * @param parent parent of the polygon + * @return polygon object + */ + sgl_obj_t *sgl_polygon_create(sgl_obj_t *parent); + + /** + * @brief set polygon vertices + * @param obj polygon object + * @param vertices vertices array + * @param count vertices count + * @return none + */ + void sgl_polygon_set_vertices(sgl_obj_t *obj, sgl_pos_t *vertices, uint16_t count); + + /** + * @brief set polygon vertices by coordinate arrays + * @param obj polygon object + * @param x_coords x coordinates array + * @param y_coords y coordinates array + * @param count vertices count + * @return none + */ + void sgl_polygon_set_vertex_coords(sgl_obj_t *obj, int16_t *x_coords, int16_t *y_coords, uint16_t count); + + /** + * @brief set polygon vertices by 2D coordinate array + * @param obj polygon object + * @param coords 2D coordinates array + * @param count vertices count + * @return none + */ + void sgl_polygon_set_vertex_array(sgl_obj_t *obj, int16_t (*coords)[2], uint16_t count); + + /** + * @brief set polygon fill color + * @param obj polygon object + * @param color fill color + * @return none + */ + void sgl_polygon_set_fill_color(sgl_obj_t *obj, sgl_color_t color); + + /** + * @brief set polygon border color + * @param obj polygon object + * @param color border color + * @return none + */ + void sgl_polygon_set_border_color(sgl_obj_t *obj, sgl_color_t color); + + /** + * @brief set polygon border width + * @param obj polygon object + * @param width border width + * @return none + */ + void sgl_polygon_set_border_width(sgl_obj_t *obj, uint8_t width); + + /** + * @brief set polygon alpha + * @param obj polygon object + * @param alpha alpha value + * @return none + */ + void sgl_polygon_set_alpha(sgl_obj_t *obj, uint8_t alpha); + + /** + * @brief set polygon pixmap + * @param obj polygon object + * @param pixmap pixmap + * @return none + * + * waiting for support + */ + // void sgl_polygon_set_pixmap(sgl_obj_t* obj, const sgl_pixmap_t* pixmap); + + /** + * @brief set polygon text + * @param obj polygon object + * @param text text to display + * @return none + */ + void sgl_polygon_set_text(sgl_obj_t *obj, const char *text); + + /** + * @brief set polygon font + * @param obj polygon object + * @param font font to use for text + * @return none + */ + void sgl_polygon_set_font(sgl_obj_t *obj, const sgl_font_t *font); + + /** + * @brief set polygon text color + * @param obj polygon object + * @param color text color + * @return none + */ + void sgl_polygon_set_text_color(sgl_obj_t *obj, sgl_color_t color); + +#ifdef __cplusplus +} +#endif + +#endif // !__SGL_POLYGON_H__ diff --git a/User/system/sgl/widgets/progress/sgl_progress.c b/User/system/sgl/widgets/progress/sgl_progress.c new file mode 100644 index 0000000..15c6cd4 --- /dev/null +++ b/User/system/sgl/widgets/progress/sgl_progress.c @@ -0,0 +1,102 @@ +/* source/widgets/sgl_progress.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_progress.h" + + +static void sgl_progress_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + sgl_area_t knob = obj->coords; + knob.x1 = obj->coords.x1 + obj->radius / 2 + obj->border; + int16_t fill_radius; + sgl_area_t rect = { + .x1 = obj->coords.x1 - progress->interval * 2 + progress->shift + obj->border + 1, + .y1 = obj->coords.y1 + obj->border + 1, + .x2 = 0, + .y2 = obj->coords.y2 - obj->border - 1, + }; + + if (progress->shift > (progress->interval + progress->knob_width)) { + progress->shift = 0; + } + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + knob.x2 = obj->coords.x1 - obj->radius / 2 - 2 + (obj->coords.x2 - obj->coords.x1) * progress->value / 100; + knob.x2 -= obj->border - 1; + sgl_draw_rect(surf, &obj->area, &obj->coords, &progress->body); + + fill_radius = sgl_min3(obj->radius, progress->knob_radius, progress->knob_width / 2); + while (rect.x2 <= knob.x2) { + rect.x2 = rect.x1 + progress->knob_width; + sgl_draw_fill_rect(surf, &knob, &rect, fill_radius, progress->color, progress->alpha); + rect.x1 = rect.x2 + progress->interval; + } + } +} + + +/** + * @brief create a progress object + * @param parent parent object of the progress + * @return progress object + */ +sgl_obj_t* sgl_progress_create(sgl_obj_t* parent) +{ + sgl_progress_t *progress = sgl_malloc(sizeof(sgl_progress_t)); + if(progress == NULL) { + SGL_LOG_ERROR("sgl_progress_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(progress, 0, sizeof(sgl_progress_t)); + + sgl_obj_t *obj = &progress->obj; + sgl_obj_init(&progress->obj, parent); + obj->construct_fn = sgl_progress_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + progress->body.alpha = SGL_THEME_ALPHA; + progress->body.color = SGL_THEME_BG_COLOR; + progress->body.border = SGL_THEME_BORDER_WIDTH; + progress->body.border_color = SGL_THEME_BORDER_COLOR; + + progress->color = SGL_THEME_COLOR; + progress->alpha = SGL_THEME_ALPHA; + progress->knob_width = 4; + progress->interval = 4; + progress->value = 50; + progress->knob_radius = 0; + + return obj; +} diff --git a/User/system/sgl/widgets/progress/sgl_progress.h b/User/system/sgl/widgets/progress/sgl_progress.h new file mode 100644 index 0000000..2c0b529 --- /dev/null +++ b/User/system/sgl/widgets/progress/sgl_progress.h @@ -0,0 +1,234 @@ +/* source/widgets/sgl_progress.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_PROGRESS_H__ +#define __SGL_PROGRESS_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl progress struct + * @obj: sgl general object + * @value: progress value + * @desc: progress description + */ +typedef struct sgl_progress { + sgl_obj_t obj; + sgl_draw_rect_t body; + sgl_color_t color; + uint8_t value; + uint8_t alpha; + uint8_t interval; + uint8_t shift; + uint8_t knob_radius; + uint8_t knob_width; +}sgl_progress_t; + + +/** + * @brief create a progress object + * @param parent parent object of the progress + * @return progress object + */ +sgl_obj_t* sgl_progress_create(sgl_obj_t* parent); + +/** + * @brief set progress track color + * @param obj progress object + * @param color track color + * @return none + */ +static inline void sgl_progress_set_track_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->body.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress track alpha + * @param obj progress object + * @param alpha track alpha + * @return none + */ +static inline void sgl_progress_set_track_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->body.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress fill color + * @param obj progress object + * @param color fill color + * @return none + */ +static inline void sgl_progress_set_fill_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress fill alpha + * @param obj progress object + * @param alpha fill alpha + * @return none + */ +static inline void sgl_progress_set_fill_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress radius + * @param obj progress object + * @param radius progress radius + * @return none + */ +static inline void sgl_progress_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + sgl_obj_set_radius(obj, radius); + progress->body.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress border width + * @param obj progress object + * @param width progress border width + * @return none + */ +static inline void sgl_progress_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->body.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress border color + * @param obj progress object + * @param color progress border color + * @return none + */ +static inline void sgl_progress_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->body.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress pixmap + * @param obj progress object + * @param pixmap progress pixmap + * @return none + */ +static inline void sgl_progress_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->body.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress fill gap size + * @param obj progress object + * @param gap progress fill gap size + * @return none + */ +static inline void sgl_progress_set_fill_gap(sgl_obj_t *obj, uint8_t gap) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->interval = gap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress fill radius + * @param obj progress object + * @param radius progress fill radius + * @return none + */ +static inline void sgl_progress_set_fill_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->knob_radius = radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress fill width + * @param obj progress object + * @param width progress fill width + * @return none + */ +static inline void sgl_progress_set_fill_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->knob_width = width; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set progress value + * @param obj progress object + * @param value progress value + * @return none + */ +static inline void sgl_progress_set_value(sgl_obj_t *obj, uint8_t value) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + progress->value = sgl_min(value, 100); + progress->shift ++; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get progress value + * @param obj progress object + * @return progress value + */ +static inline uint8_t sgl_progress_get_value(sgl_obj_t *obj) +{ + sgl_progress_t *progress = sgl_container_of(obj, sgl_progress_t, obj); + return progress->value; +} + + +#endif // !__SGL_PROGRESS_H__ diff --git a/User/system/sgl/widgets/rectangle/sgl_rectangle.c b/User/system/sgl/widgets/rectangle/sgl_rectangle.c new file mode 100644 index 0000000..edadd08 --- /dev/null +++ b/User/system/sgl/widgets/rectangle/sgl_rectangle.c @@ -0,0 +1,103 @@ +/* source/widgets/sgl_rectangle.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_rectangle.h" + + +/** + * @brief rectangle construct callback + * @param surf: surface + * @param obj: object + * @param evt: event parameter + * @retval none + */ +static void sgl_rectangle_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_rectangle_t *rect = sgl_container_of(obj, sgl_rectangle_t, obj); + sgl_draw_rect_t desc = { + .color = rect->color, + .alpha = rect->alpha, + .border = obj->border, + .border_color = rect->border_color, + .pixmap = rect->pixmap, + .radius = obj->radius, + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + + sgl_draw_rect(surf, &obj->area, &obj->coords, &desc); + } + else if(evt->type == SGL_EVENT_PRESSED) { + if(sgl_obj_is_flexible(obj)) { + sgl_obj_size_zoom(obj, 2); + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + if(sgl_obj_is_flexible(obj)) { + sgl_obj_size_zoom(obj, -2); + } + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a rectangle + * @param parent: parent object + * @retval rectangle object + */ +sgl_obj_t* sgl_rect_create(sgl_obj_t* parent) +{ + sgl_rectangle_t *rect = sgl_malloc(sizeof(sgl_rectangle_t)); + if(rect == NULL) { + SGL_LOG_ERROR("sgl_rect_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(rect, 0, sizeof(sgl_rectangle_t)); + + sgl_obj_t *obj = &rect->obj; + sgl_obj_init(&rect->obj, parent); + sgl_obj_set_unflexible(obj); + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + obj->construct_fn = sgl_rectangle_construct_cb; + + rect->alpha = SGL_THEME_ALPHA; + rect->color = SGL_THEME_COLOR; + rect->border_color = SGL_THEME_BORDER_COLOR; + rect->pixmap = NULL; + + return obj; +} diff --git a/User/system/sgl/widgets/rectangle/sgl_rectangle.h b/User/system/sgl/widgets/rectangle/sgl_rectangle.h new file mode 100644 index 0000000..ffefeb1 --- /dev/null +++ b/User/system/sgl/widgets/rectangle/sgl_rectangle.h @@ -0,0 +1,135 @@ +/* source/widgets/sgl_rectangle.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_RECTANGLE_H__ +#define __SGL_RECTANGLE_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl rectangle + * @obj: sgl general object + * @desc: rectangle draw description + */ +typedef struct sgl_rectangle { + sgl_obj_t obj; + sgl_color_t color; + sgl_color_t border_color; + const sgl_pixmap_t *pixmap; + uint8_t alpha; +}sgl_rectangle_t; + + +/** + * @brief create a rectangle + * @param parent: parent object + * @retval rectangle object + */ +sgl_obj_t* sgl_rect_create(sgl_obj_t* parent); + + +/** + * @brief set rectangle color + * @param obj: rectangle object + * @param color: rectangle color + * @retval none + */ +static inline void sgl_rect_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_rectangle_t *rect = sgl_container_of(obj, sgl_rectangle_t, obj); + rect->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set rectangle alpha + * @param obj: rectangle object + * @param alpha: rectangle alpha + * @retval none + */ +static inline void sgl_rect_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_rectangle_t *rect = sgl_container_of(obj, sgl_rectangle_t, obj); + rect->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set rectangle radius + * @param obj: rectangle object + * @param radius: rectangle radius + * @retval none + */ +static inline void sgl_rect_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set rectangle border width + * @param obj: rectangle object + * @param width: rectangle border width + * @retval none + */ +static inline void sgl_rect_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set rectangle border color + * @param obj: rectangle object + * @param color: rectangle border color + * @retval none + */ +static inline void sgl_rect_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_rectangle_t *rect = sgl_container_of(obj, sgl_rectangle_t, obj); + rect->border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set rectangle pixmap + * @param obj: rectangle object + * @param pixmap: rectangle pixmap + * @retval none + */ +static inline void sgl_rect_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_rectangle_t *rect = sgl_container_of(obj, sgl_rectangle_t, obj); + rect->pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_RECTANGLE_H__ diff --git a/User/system/sgl/widgets/ring/sgl_ring.c b/User/system/sgl/widgets/ring/sgl_ring.c new file mode 100644 index 0000000..a8fbf7e --- /dev/null +++ b/User/system/sgl/widgets/ring/sgl_ring.c @@ -0,0 +1,86 @@ +/* source/widgets/sgl_ring.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_ring.h" + + +static void sgl_ring_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_ring_t *ring = sgl_container_of(obj, sgl_ring_t, obj); + int16_t cx, cy; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + cx = (obj->coords.x2 + obj->coords.x1) / 2; + cy = (obj->coords.y2 + obj->coords.y1) / 2; + sgl_draw_fill_ring(surf, &obj->area, cx, cy, ring->radius_in, ring->radius_out, ring->color, ring->alpha); + } + else if(evt->type == SGL_EVENT_DRAW_INIT) { + if(ring->radius_out == -1) { + ring->radius_out = (obj->coords.x2 - obj->coords.x1) / 2; + } + + if(ring->radius_in == -1) { + ring->radius_in = ring->radius_out - 2; + } + } +} + + +/** + * @brief Create a ring object + * @param parent The parent object of the ring + * @return The ring object + */ +sgl_obj_t* sgl_ring_create(sgl_obj_t* parent) +{ + sgl_ring_t *ring = sgl_malloc(sizeof(sgl_ring_t)); + if(ring == NULL) { + SGL_LOG_ERROR("sgl_ring_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(ring, 0, sizeof(sgl_ring_t)); + + sgl_obj_t *obj = &ring->obj; + sgl_obj_init(&ring->obj, parent); + obj->construct_fn = sgl_ring_construct_cb; + + obj->needinit = 1; + ring->radius_in = -1; + ring->radius_out = -1; + ring->alpha = SGL_THEME_ALPHA; + ring->color = SGL_THEME_COLOR; + + return obj; +} + diff --git a/User/system/sgl/widgets/ring/sgl_ring.h b/User/system/sgl/widgets/ring/sgl_ring.h new file mode 100644 index 0000000..ef42ad9 --- /dev/null +++ b/User/system/sgl/widgets/ring/sgl_ring.h @@ -0,0 +1,103 @@ +/* source/widgets/sgl_ring.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_RING_H__ +#define __SGL_RING_H__ + + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl ring + * @obj: sgl general object + * @desc: ring draw description + */ +typedef struct sgl_ring { + sgl_obj_t obj; + int16_t radius_in; + int16_t radius_out; + sgl_color_t color; + uint8_t alpha; +}sgl_ring_t; + + +/** + * @brief Create a ring object + * @param parent The parent object of the ring + * @return The ring object + */ +sgl_obj_t* sgl_ring_create(sgl_obj_t* parent); + + +/** + * @brief Set the ring color + * @param obj The ring object + * @param color The ring color + * @return none + */ +static inline void sgl_ring_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_ring_t *ring = sgl_container_of(obj, sgl_ring_t, obj); + ring->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set the ring alpha + * @param obj The ring object + * @param alpha The ring alpha + * @return none + * @note The alpha value range is 0~255 + */ +static inline void sgl_ring_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_ring_t *ring = sgl_container_of(obj, sgl_ring_t, obj); + ring->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set the ring radius + * @param obj The ring object + * @param radius_in The ring inner radius + * @param radius_out The ring outer radius + * @return none + */ +static inline void sgl_ring_set_radius(sgl_obj_t *obj, uint16_t radius_in, uint16_t radius_out) +{ + sgl_ring_t *ring = sgl_container_of(obj, sgl_ring_t, obj); + ring->radius_in = radius_in; + sgl_obj_set_radius(obj, radius_out); + ring->radius_out = obj->radius; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_RING_H__ diff --git a/User/system/sgl/widgets/scope/sgl_scope.c b/User/system/sgl/widgets/scope/sgl_scope.c new file mode 100644 index 0000000..308527f --- /dev/null +++ b/User/system/sgl/widgets/scope/sgl_scope.c @@ -0,0 +1,442 @@ +/* source/widgets/sgl_scope.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include "sgl_scope.h" + + +// Draw a dashed line using Bresenham's algorithm with dash pattern +static void draw_dashed_line(sgl_surf_t *surf, sgl_area_t *area, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t gap, sgl_color_t color) +{ + int16_t dx = sgl_abs(x1 - x0); + int16_t dy = sgl_abs(y1 - y0); + int16_t sx = (x0 < x1) ? 1 : -1; + int16_t sy = (y0 < y1) ? 1 : -1; + int16_t err = dx - dy; + int16_t e2; + int16_t dash_len = 0; + + sgl_area_t clip_area = { + .x1 = surf->x1, + .y1 = surf->y1, + .x2 = surf->x2, + .y2 = surf->y2 + }; + + sgl_area_selfclip(&clip_area, area); + + while (1) { + // Draw dash segment + if (dash_len < gap) { + // Check if point is within clipping area + if (x0 >= clip_area.x1 && x0 <= clip_area.x2 && y0 >= clip_area.y1 && y0 <= clip_area.y2) { + sgl_color_t *buf = sgl_surf_get_buf(surf, x0 - surf->x1, y0 - surf->y1); + *buf = color; + } + dash_len++; + } else if (dash_len < 2 * gap) { + // Skip drawing (gap segment) + dash_len++; + } else { + // Reset dash counter + dash_len = 0; + } + + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } +} + + +// Custom line drawing function supporting variable line width +static void custom_draw_line(sgl_surf_t *surf, sgl_area_t *area, sgl_pos_t start, sgl_pos_t end, sgl_color_t color, int16_t width) +{ + int16_t x0 = start.x; + int16_t y0 = start.y; + int16_t x1 = end.x; + int16_t y1 = end.y; + + // Handle invalid line width (zero or negative) + if (width <= 0) return; + + // For line width = 1, use standard Bresenham algorithm + if (width == 1) { + int16_t dx = sgl_abs(x1 - x0); + int16_t dy = sgl_abs(y1 - y0); + int16_t sx = (x0 < x1) ? 1 : -1; + int16_t sy = (y0 < y1) ? 1 : -1; + int16_t err = dx - dy; + int16_t e2; + + sgl_area_t clip_area = { + .x1 = surf->x1, + .y1 = surf->y1, + .x2 = surf->x2, + .y2 = surf->y2 + }; + + while (1) { + // Check if point is within clipping area + if (x0 >= clip_area.x1 && x0 <= clip_area.x2 && y0 >= clip_area.y1 && y0 <= clip_area.y2) { + sgl_color_t *buf = sgl_surf_get_buf(surf, x0 - surf->x1, y0 - surf->y1); + *buf = color; + } + + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } + return; + } + + // For line width > 1, draw main line plus perpendicular offsets to simulate thickness + int16_t dx = sgl_abs(x1 - x0); + int16_t dy = sgl_abs(y1 - y0); + int16_t sx = (x0 < x1) ? 1 : -1; + int16_t sy = (y0 < y1) ? 1 : -1; + int16_t err = dx - dy; + int16_t e2; + + sgl_area_t clip_area = { + .x1 = surf->x1, + .y1 = surf->y1, + .x2 = surf->x2, + .y2 = surf->y2 + }; + + sgl_area_selfclip(&clip_area, area); + + // Compute half-width for symmetric thickening + int16_t half_width = width / 2; + + while (1) { + // Draw current pixel and its perpendicular neighbors to form line thickness + for (int16_t w = -half_width; w <= half_width; w++) { + int16_t px, py; + + // Determine offset direction based on dominant axis + if (dx > dy) { // Dominant X-axis direction + px = x0; + py = y0 + w; + } else { // Dominant Y-axis direction + px = x0 + w; + py = y0; + } + + // Check if point is within clipping area + if (px >= clip_area.x1 && px <= clip_area.x2 && py >= clip_area.y1 && py <= clip_area.y2) { + sgl_color_t *buf = sgl_surf_get_buf(surf, px - surf->x1, py - surf->y1); + *buf = color; + } + } + + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } +} + +// Oscilloscope drawing callback function +static void scope_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_scope_t *scope = (sgl_scope_t*)obj; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + // Skip drawing if object is completely outside screen bounds + if (obj->area.x2 < surf->x1 || obj->area.x1 > surf->x2 || + obj->area.y2 < surf->y1 || obj->area.y1 > surf->y2) { + return; // Object is fully off-screen; no need to draw + } + + // Draw background + sgl_draw_rect_t bg_rect = { + .color = scope->bg_color, + .alpha = scope->alpha, + .radius = 0, + .border = scope->border_width, + }; + + sgl_draw_rect(surf, &obj->area, &obj->coords, &bg_rect); + + // Compute waveform display parameters + int16_t display_min = scope->min_value; + int16_t display_max = scope->max_value; + int16_t actual_min = display_min; // Actual min/max of waveform data (for labels) + int16_t actual_max = display_max; // Actual max of waveform data (for labels) + + // If auto-scaling is enabled, recalculate min/max from current buffer data + if (scope->auto_scale) { + // Recalculate running_min and running_max based on current data in buffer + if (scope->display_count > 0) { + display_min = scope->data_buffer[0]; + display_max = scope->data_buffer[0]; + + // Iterate through all data points in buffer to find min/max + uint32_t end_index = (scope->display_count < scope->data_len) ? scope->display_count : scope->data_len; + for (uint32_t i = 0; i < end_index; i++) { + int16_t val = scope->data_buffer[i]; + if (val < display_min) display_min = val; + if (val > display_max) display_max = val; + } + + // Save actual data min/max for label display + actual_min = display_min; + actual_max = display_max; + + // Update running values for next frame + scope->running_min = display_min; + scope->running_max = display_max; + } + + // Add margin to prevent waveform from touching borders + int32_t margin = (int32_t)(display_max - display_min) / 10; + if (margin == 0) margin = 1; + + display_min = (display_min > INT16_MIN + margin) ? display_min - margin : INT16_MIN; + display_max = (display_max < INT16_MAX - margin) ? display_max + margin : INT16_MAX; + } + + // Avoid division by zero if min equals max + if (display_min == display_max) { + if (display_max < INT16_MAX) { + display_max++; + } else { + display_min--; + } + } + + // Draw grid lines + int16_t width = obj->coords.x2 - obj->coords.x1; + int16_t height = obj->coords.y2 - obj->coords.y1; + int16_t x_center = (obj->coords.x1 + obj->coords.x2) / 2; + int16_t y_center = obj->coords.y1 + (int32_t)(height * (display_max - (display_min + display_max) / 2)) / (display_max - display_min); + + // Draw horizontal center line (midpoint of display range) + if (scope->grid_style) { + // Draw dashed line + draw_dashed_line(surf, &obj->area, obj->coords.x1, y_center, obj->coords.x2, y_center, scope->grid_style, scope->grid_color); + } else { + // Draw solid line + sgl_draw_fill_hline(surf, &obj->area, y_center, obj->coords.x1, obj->coords.x2, 1, scope->grid_color, scope->alpha); + } + + // Draw vertical center line + if (scope->grid_style) { + // Draw dashed line + draw_dashed_line(surf, &obj->area, x_center, obj->coords.y1, x_center, obj->coords.y2, scope->grid_style, scope->grid_color); + } else { + // Draw solid line + sgl_draw_fill_vline(surf, &obj->area, x_center, obj->coords.y1, obj->coords.y2, 1, scope->grid_color, scope->alpha); + } + + // Draw vertical grid lines (10 divisions) + for (int i = 1; i < 10; i++) { + int16_t x_pos = obj->coords.x1 + (width * i / 10); + + if (scope->grid_style) { + // Draw dashed line + draw_dashed_line(surf, &obj->area, x_pos, obj->coords.y1, x_pos, obj->coords.y2, scope->grid_style, scope->grid_color); + } else { + // Draw solid line + sgl_draw_fill_vline(surf, &obj->area, x_pos, obj->coords.y1, obj->coords.y2, 1, scope->grid_color, scope->alpha); + } + } + + // Draw horizontal grid lines (10 divisions) + for (int i = 1; i < 10; i++) { + int16_t y_pos = obj->coords.y1 + (height * i / 10); + if (scope->grid_style) { + // Draw dashed line + draw_dashed_line(surf, &obj->area, obj->coords.x1, y_pos, obj->coords.x2, y_pos, scope->grid_style, scope->grid_color); + } else { + // Draw solid line + sgl_draw_fill_hline(surf, &obj->area, y_pos, obj->coords.x1, obj->coords.x2, 1, scope->grid_color, scope->alpha); + } + } + + // Draw waveform data + if (scope->display_count > 1) { + sgl_pos_t start, end; + + // Determine number of points to display + uint32_t display_points = scope->max_display_points > 0 ? scope->max_display_points : scope->data_len; + if (display_points > scope->data_len) display_points = scope->data_len; + + // Number of actual data points to render + uint32_t data_points = scope->display_count < display_points ? scope->display_count : display_points; + + // Compute index of the most recent data point (rightmost on screen) + uint32_t last_index = (scope->current_index == 0) ? scope->data_len - 1 : scope->current_index - 1; + int16_t last_value = scope->data_buffer[last_index]; + + // Clamp value to display range + if (last_value < display_min) last_value = display_min; + if (last_value > display_max) last_value = display_max; + + start.x = obj->coords.x2; // Rightmost X position + start.y = obj->coords.y2 - ((int32_t)(last_value - display_min) * height) / (display_max - display_min); + + // Draw waveform from right to left + for (uint32_t i = 1; i < data_points; i++) { + //int index = (scope->current_index >= i) ? scope->current_index - i : scope->data_len - (i - scope->current_index); + uint32_t prev_index = (scope->current_index >= i + 1) ? scope->current_index - (i + 1) : scope->data_len - (i + 1 - scope->current_index); + + int16_t current_value = scope->data_buffer[prev_index]; + + // Clamp value to display range + current_value = sgl_clamp(current_value, display_min, display_max); + + end.x = obj->coords.x2 - (i * width / (data_points - 1)); // Move leftward + end.y = obj->coords.y2 - ((int32_t)(current_value - display_min) * height) / (display_max - display_min); + + custom_draw_line(surf, &obj->area, start, end, scope->waveform_color, scope->line_width); + + start = end; + } + } + + // Draw Y-axis labels if enabled and font is set + if (scope->show_y_labels && scope->y_label_font) { + char label_text[16]; + sgl_area_t text_area = { + .x1 = obj->coords.x1 + 2, + .y1 = obj->coords.y1, + .x2 = obj->coords.x1 + 50, + .y2 = obj->coords.y2 + }; + + sgl_area_selfclip(&text_area, &obj->area); + + // Display actual maximum value of waveform data + sprintf(label_text, "%d", actual_max); + sgl_draw_string(surf, &text_area, obj->coords.x1 + 2, obj->coords.y1 + 2, + label_text, scope->y_label_color, scope->alpha, scope->y_label_font); + + // Display actual minimum value of waveform data + sprintf(label_text, "%d", actual_min); + sgl_draw_string(surf, &text_area, obj->coords.x1 + 2, obj->coords.y2 - scope->y_label_font->font_height - 2, + label_text, scope->y_label_color, scope->alpha, scope->y_label_font); + + // Display mid-range value of actual waveform + int16_t mid_value = (actual_max + actual_min) / 2; + sprintf(label_text, "%d", mid_value); + sprintf(label_text, "%u", mid_value); + sgl_draw_string(surf, &text_area, obj->coords.x1 + 2, y_center - scope->y_label_font->font_height/2, + label_text, scope->y_label_color, scope->alpha, scope->y_label_font); + } + } +} + + +// Create an oscilloscope object +sgl_obj_t* sgl_scope_create(sgl_obj_t* parent) +{ + sgl_scope_t *scope = sgl_malloc(sizeof(sgl_scope_t)); + if(scope == NULL) { + return NULL; + } + + memset(scope, 0, sizeof(sgl_scope_t)); + + sgl_obj_t *obj = &scope->obj; + sgl_obj_init(obj, parent); + obj->construct_fn = scope_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + // Initialize default parameters + scope->waveform_color = sgl_rgb(0, 255, 0); // Green waveform + scope->bg_color = sgl_rgb(0, 0, 0); // Black background + scope->grid_color = sgl_rgb(50, 50, 50); // Gray grid lines + scope->border_width = 0; // border width is 0 + scope->border_color = sgl_rgb(150, 150, 150); // Light gray outer border + scope->min_value = 0; + scope->max_value = 0xFFFF; + scope->running_min = INT16_MAX; // Initialize runtime minimum to max int16_t value + scope->running_max = INT16_MIN; // Initialize runtime maximum to min int16_t value + scope->auto_scale = 1; // Enable auto-scaling by default + scope->line_width = 2; // Default line thickness + scope->max_display_points = 0; // Display all points by default + scope->show_y_labels = 0; // Hide Y-axis labels by default + scope->alpha = SGL_ALPHA_MAX; // Fully opaque by default + scope->grid_style = 0; // Solid grid lines by default + scope->y_label_font = NULL; // No font by default + scope->y_label_color = sgl_rgb(255, 255, 255); // White label color + scope->display_count = 0; // No data initially + + return obj; +} + +/** + * @brief Append a new data point to the oscilloscope + * @param obj The oscilloscope object + * @param value The new data point + * @note This function appends a new data point to the oscilloscope. + * If the oscilloscope is configured to auto-scale, the function updates the running minimum and maximum values. + * The function also updates the display count and marks the oscilloscope object as dirty. + */ +void sgl_scope_append_data(sgl_obj_t* obj, int16_t value) +{ + sgl_scope_t *scope = (sgl_scope_t*)obj; + + // Simply append the data point to the buffer + // Min/max will be recalculated during drawing if auto-scale is enabled + scope->data_buffer[scope->current_index] = value; + + if (sgl_is_pow2(scope->data_len)) { + scope->current_index = (scope->current_index + 1) & (scope->data_len - 1); + } else { + scope->current_index = (scope->current_index + 1) % scope->data_len; + } + + // update display count + if (scope->display_count < scope->data_len) { + scope->display_count++; + } + + sgl_obj_set_dirty(obj); +} diff --git a/User/system/sgl/widgets/scope/sgl_scope.h b/User/system/sgl/widgets/scope/sgl_scope.h new file mode 100644 index 0000000..d1cd0c1 --- /dev/null +++ b/User/system/sgl/widgets/scope/sgl_scope.h @@ -0,0 +1,304 @@ +/* source/widgets/sgl_scope.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_SCOPE_H__ +#define __SGL_SCOPE_H__ + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sgl_obj_t obj; + int16_t *data_buffer; // channel data buffer + uint32_t data_len; // data length + sgl_color_t waveform_color; // waveform color + sgl_color_t bg_color; // background color + sgl_color_t grid_color; // grid line color + sgl_color_t border_color; // border color + int16_t min_value; // min value of data + int16_t max_value; // max value of data + int16_t running_min; // min value of runtime + int16_t running_max; // max value of runtime + uint8_t auto_scale : 1; // whether to automatically scale + uint8_t show_y_labels : 1; // whether to show Y axis labels + uint8_t border_width; // outer border width + uint8_t line_width; // width of waveform line + uint8_t display_count; // data count that has been displayed + uint32_t max_display_points; // max display points + uint8_t alpha; // aplha of waveform + uint8_t grid_style; // grid line style(0-solid line,other: dashed line + const sgl_font_t *y_label_font; // font of Y axis labels + sgl_color_t y_label_color; // color of Y axis labels + uint32_t current_index; // current data index +} sgl_scope_t; + + +/** + * @brief create scope object + * @param parent parent object + * @return scope object + */ +sgl_obj_t* sgl_scope_create(sgl_obj_t* parent); + +/** + * @brief set scope data buffer + * @param obj scope object + * @param data_buffer data buffer + * @param data_len data length + * @return none + */ +static inline void sgl_scope_set_data_buffer(sgl_obj_t* obj, int16_t *data_buffer, uint32_t data_len) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->data_buffer = data_buffer; + scope->data_len = data_len; +} + +/** + * @brief Append a new data point to the oscilloscope + * @param obj The oscilloscope object + * @param value The new data point + * @note This function appends a new data point to the oscilloscope. + * If the oscilloscope is configured to auto-scale, the function updates the running minimum and maximum values. + * The function also updates the display count and marks the oscilloscope object as dirty. + */ +void sgl_scope_append_data(sgl_obj_t* obj, int16_t value); + +/** + * @brief get scope data + * @param obj scope object + * @param index data index + * @return data value + */ +static inline int16_t sgl_scope_get_data(sgl_obj_t* obj, uint32_t index) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + if (index >= scope->data_len) + return 0; + + return scope->data_buffer[index]; +} + +/** + * @brief set scope max display points + * @param obj scope object + * @param max_points max display points + * @return none + */ +static inline void sgl_scope_set_max_display_points(sgl_obj_t* obj, uint8_t max_points) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->max_display_points = max_points; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope waveform color + * @param obj scope object + * @param color waveform color + * @return none + */ +static inline void sgl_scope_set_waveform_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->waveform_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope background color + * @param obj scope object + * @param color background color + * @return none + */ +static inline void sgl_scope_set_bg_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope grid line color + * @param obj scope object + * @param color grid line color + * @return none + */ +static inline void sgl_scope_set_grid_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->grid_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope range + * @param obj scope object + * @param min_value minimum value + * @param max_value maximum value + * @return none + */ +static inline void sgl_scope_set_range(sgl_obj_t* obj, uint16_t min_value, uint16_t max_value) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->min_value = min_value; + scope->max_value = max_value; + scope->auto_scale = 0; // disable auto scale + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope line width + * @param obj scope object + * @param width line width + * @return none + */ +static inline void sgl_scope_set_line_width(sgl_obj_t* obj, uint8_t width) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->line_width = width; + sgl_obj_set_dirty(obj); +} + +/** + * @brief enable/disable auto scale + * @param obj scope object + * @param enable enable/disable + * @return none + */ +static inline void sgl_scope_enable_auto_scale(sgl_obj_t* obj, bool enable) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->auto_scale = (uint8_t)enable; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope alpha + * @param obj scope object + * @param alpha alpha + * @return none + */ +static inline void sgl_scope_set_alpha(sgl_obj_t* obj, uint8_t alpha) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief show/hide Y axis labels + * @param obj scope object + * @param show show/hide + * @return none + */ +static inline void sgl_scope_show_y_labels(sgl_obj_t* obj, bool show) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->show_y_labels = (uint8_t)show; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope Y axis labels font + * @param obj scope object + * @param font font + * @return none + */ +static inline void sgl_scope_set_y_label_font(sgl_obj_t* obj, const sgl_font_t *font) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->y_label_font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope Y axis labels color + * @param obj scope object + * @param color color + * @return none + */ +static inline void sgl_scope_set_y_label_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->y_label_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope border color + * @param obj scope object + * @param color border color + * @return none + */ +static inline void sgl_scope_set_border_color(sgl_obj_t* obj, sgl_color_t color) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope border width + * @param obj scope object + * @param width border width + * @return none + */ +static inline void sgl_scope_set_border_width(sgl_obj_t* obj, uint8_t width) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->border_width = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set scope grid line + * @param obj scope object + * @param style grid size, 0: solid line,other: dashed line + * @return none + */ +static inline void sgl_scope_set_grid_line(sgl_obj_t* obj, uint8_t grid) +{ + sgl_scope_t *scope = sgl_container_of(obj, sgl_scope_t, obj); + scope->grid_style = grid; + sgl_obj_set_dirty(obj); +} + + +#ifdef __cplusplus +} +#endif + +#endif // SGL_SCOPE_H diff --git a/User/system/sgl/widgets/scroll/sgl_scroll.c b/User/system/sgl/widgets/scroll/sgl_scroll.c new file mode 100644 index 0000000..c708173 --- /dev/null +++ b/User/system/sgl/widgets/scroll/sgl_scroll.c @@ -0,0 +1,156 @@ +/* source/widgets/sgl_scroll.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_scroll.h" + +#define SGL_SCROLL_DEFAULT_WIDTH (10) + +/** + * @brief scroll construct callback + * @param surf pointer to surface + * @param obj pointer to object + * @param evt pointer to event + * @return none + */ +static void sgl_scroll_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + sgl_rect_t fill = {0}; + sgl_color_t tmp = scroll->desc.color; + uint16_t len = 0, pos = 0; + scroll->desc.radius = sgl_min(scroll->desc.radius, scroll->width / 2); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if (scroll->bind && (scroll->hidden != 1)) { + + if (scroll->direct == SGL_DIRECT_VERTICAL) { + obj->coords.x2 = scroll->bind->coords.x2; + obj->coords.y2 = scroll->bind->coords.y2; + obj->coords.y1 = scroll->bind->coords.y1; + obj->coords.x1 = obj->coords.x2 - scroll->width; + + len = sgl_max((obj->coords.y2 - obj->coords.y1) / 8, scroll->desc.radius * 2 + 1); + pos = scroll->value * (obj->coords.y2 - obj->coords.y1 - len) / 100; + + fill.x1 = obj->coords.x1 + scroll->desc.border; + fill.x2 = obj->coords.x2 - scroll->desc.border; + //fill.y1 = pos + scroll->desc.border; + //fill.y2 = pos + len - scroll->desc.border; + fill.y1 = obj->coords.y1+pos + scroll->desc.border; + fill.y2 = obj->coords.y1+pos + len - scroll->desc.border; + } + else if (scroll->direct == SGL_DIRECT_HORIZONTAL) { + obj->coords.x1 = scroll->bind->coords.x1; + obj->coords.y2 = scroll->bind->coords.y2; + obj->coords.x2 = scroll->bind->coords.x2; + obj->coords.y1 = obj->coords.y2 - scroll->width; + + len = sgl_max((obj->coords.x2 - obj->coords.x1) / 8, scroll->desc.radius * 2 + 1); + pos = scroll->value * (obj->coords.x2 - obj->coords.x1 - len) / 100; + + fill.y1 = obj->coords.y1 + scroll->desc.border; + fill.y2 = obj->coords.y2 - scroll->desc.border; + //fill.x1 = pos + scroll->desc.border; + //fill.x2 = pos + len - scroll->desc.border; + fill.x1 =obj->coords.x1+ pos + scroll->desc.border; + fill.x2 =obj->coords.x2+ pos + len - scroll->desc.border; + } + + sgl_draw_rect(surf, &obj->coords, &obj->coords, &scroll->desc); + tmp = sgl_color_mixer(tmp, SGL_THEME_BG_COLOR, 128); + sgl_draw_fill_rect(surf, &fill, &fill, scroll->desc.radius - scroll->desc.border, tmp, scroll->desc.alpha); + } + } + else if (evt->type == SGL_EVENT_MOVE_DOWN) { + if (scroll->direct == SGL_DIRECT_VERTICAL && scroll->value < 100) { + scroll->value ++; + sgl_obj_move_child_pos_y(scroll->bind, evt->distance); + } + } + else if(evt->type == SGL_EVENT_MOVE_UP) { + if (scroll->direct == SGL_DIRECT_VERTICAL && scroll->value > 0) { + scroll->value --; + sgl_obj_move_child_pos_y(scroll->bind, -evt->distance); + } + } + else if(evt->type == SGL_EVENT_MOVE_LEFT) { + if (scroll->direct == SGL_DIRECT_HORIZONTAL && scroll->value > 0) { + scroll->value --; + sgl_obj_move_child_pos_x(scroll->bind, -evt->distance); + } + } + else if(evt->type == SGL_EVENT_MOVE_RIGHT) { + if (scroll->direct == SGL_DIRECT_HORIZONTAL && scroll->value < 100) { + scroll->value ++; + sgl_obj_move_child_pos_x(scroll->bind, evt->distance); + } + } +} + + +/** + * @brief create scroll object + * @param parent pointer to parent object + * @return pointer to scroll object + */ +sgl_obj_t* sgl_scroll_create(sgl_obj_t* parent) +{ + sgl_scroll_t *scroll = sgl_malloc(sizeof(sgl_scroll_t)); + if(scroll == NULL) { + SGL_LOG_ERROR("sgl_scroll_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(scroll, 0, sizeof(sgl_scroll_t)); + + sgl_obj_t *obj = &scroll->obj; + sgl_obj_init(&scroll->obj, parent); + obj->construct_fn = sgl_scroll_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + obj->movable = 1; + obj->clickable = 1; + + scroll->bind = NULL; + scroll->direct = SGL_DIRECT_VERTICAL; + scroll->hidden = false; + scroll->value = 0; + scroll->width = SGL_SCROLL_DEFAULT_WIDTH; + scroll->desc.radius = SGL_THEME_RADIUS; + scroll->desc.color = SGL_THEME_COLOR; + scroll->desc.alpha = SGL_THEME_ALPHA; + scroll->desc.border_color = SGL_THEME_BORDER_COLOR; + scroll->desc.border = 2; + scroll->desc.pixmap = NULL; + + return obj; +} diff --git a/User/system/sgl/widgets/scroll/sgl_scroll.h b/User/system/sgl/widgets/scroll/sgl_scroll.h new file mode 100644 index 0000000..8badda8 --- /dev/null +++ b/User/system/sgl/widgets/scroll/sgl_scroll.h @@ -0,0 +1,149 @@ +/* source/widgets/sgl_scroll.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_SCROLL_H__ +#define __SGL_SCROLL_H__ + +#include +#include +#include +#include +#include +#include +#include + + +typedef struct sgl_scroll { + sgl_obj_t obj; + sgl_obj_t *bind; + sgl_draw_rect_t desc; + uint8_t width; + uint8_t value; + uint8_t direct; + uint8_t hidden; +} sgl_scroll_t; + + +/** + * @brief create scroll object + * @param parent pointer to parent object + * @return pointer to scroll object + */ +sgl_obj_t* sgl_scroll_create(sgl_obj_t* parent); + + +static inline void sgl_scroll_bind_obj(sgl_obj_t *obj, sgl_obj_t *bind) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->bind = bind; + sgl_obj_set_dirty(obj); +} + + +static inline void sgl_scroll_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->desc.color = color; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_radius(sgl_obj_t *obj, uint16_t radius) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->desc.radius = radius; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->desc.border_color = color; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->desc.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + + + +static inline void sgl_scroll_set_width(sgl_obj_t *obj, uint8_t width) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->width = width; + sgl_obj_set_dirty(obj); +} + + +static inline void sgl_scroll_set_direct(sgl_obj_t *obj, uint8_t direct) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->direct = direct; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_hidden(sgl_obj_t *obj, uint8_t hidden) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->hidden = hidden; + sgl_obj_set_dirty(obj); +} + +static inline void sgl_scroll_set_value(sgl_obj_t *obj, uint8_t value) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + scroll->value = value; + sgl_obj_set_dirty(obj); +} + + +static inline uint8_t sgl_scroll_get_value(sgl_obj_t *obj) +{ + SGL_ASSERT(obj != NULL); + sgl_scroll_t *scroll = sgl_container_of(obj, sgl_scroll_t, obj); + return scroll->value; +} + +#endif // !__SGL_SCROLL_H__ diff --git a/User/system/sgl/widgets/slider/sgl_slider.c b/User/system/sgl/widgets/slider/sgl_slider.c new file mode 100644 index 0000000..c0958bc --- /dev/null +++ b/User/system/sgl/widgets/slider/sgl_slider.c @@ -0,0 +1,129 @@ +/* source/widgets/sgl_slider.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_slider.h" + + +static void sgl_slider_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + int16_t w = obj->coords.x2 - obj->coords.x1 + 1; + int16_t h = obj->coords.y2 - obj->coords.y1 + 1; + int16_t knob_r, fill_pos, thickness, radius; + sgl_rect_t bar; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if(slider->direct == SGL_DIRECT_HORIZONTAL) { + knob_r = h / 2 - 1; + thickness = sgl_min(slider->thickness, knob_r); + bar.x1 = obj->coords.x1 + knob_r; + bar.x2 = obj->coords.x2 - knob_r; + bar.y1 = obj->coords.y1 + (h - thickness) / 2; + bar.y2 = bar.y1 + thickness - 1; + fill_pos = obj->coords.x1 + (obj->coords.x2 - obj->coords.x1) * slider->value / 100 - obj->border; + + radius = sgl_min(thickness / 2, obj->radius); + sgl_draw_fill_rect(surf, &obj->area, &bar, radius, slider->track_color, SGL_ALPHA_MAX); + fill_pos = sgl_clamp(fill_pos, bar.x1, bar.x2); + bar.x2 = fill_pos; + sgl_draw_fill_rect(surf, &obj->area, &bar, radius, slider->fill_color, SGL_ALPHA_MAX); + sgl_draw_fill_circle(surf, &obj->area, fill_pos, sgl_mid(bar.y1, bar.y2), knob_r, slider->knob_color, SGL_ALPHA_MAX); + } + else { + knob_r = w / 2 - 1; + thickness = sgl_min(slider->thickness, knob_r); + bar.y1 = obj->coords.y1 + knob_r; + bar.y2 = obj->coords.y2 - knob_r; + bar.x2 = obj->coords.x2 - (w - thickness) / 2; + bar.x1 = bar.x2 - thickness + 1; + fill_pos = obj->coords.y2 - (obj->coords.y2 - obj->coords.y1) * slider->value / 100 + obj->border; + + radius = sgl_min(thickness / 2, obj->radius); + sgl_draw_fill_rect(surf, &obj->area, &bar, radius, slider->track_color, SGL_ALPHA_MAX); + fill_pos = sgl_clamp(fill_pos, bar.y1, bar.y2); + bar.y1 = fill_pos; + sgl_draw_fill_rect(surf, &obj->area, &bar, radius, slider->fill_color, SGL_ALPHA_MAX); + sgl_draw_fill_circle(surf, &obj->area, sgl_mid(bar.x1, bar.x2), fill_pos, knob_r, slider->knob_color, SGL_ALPHA_MAX); + } + } + else if(evt->type == SGL_EVENT_PRESSED || + evt->type == SGL_EVENT_MOVE_DOWN || evt->type == SGL_EVENT_MOVE_UP || evt->type == SGL_EVENT_MOVE_LEFT || evt->type == SGL_EVENT_MOVE_RIGHT + ) { + if(slider->direct == SGL_DIRECT_HORIZONTAL) { + slider->value = (evt->pos.x - obj->coords.x1) * 100 / (obj->coords.x2 - obj->coords.x1); + } + else { + slider->value = (obj->coords.y2 - evt->pos.y) * 100 / (obj->coords.y2 - obj->coords.y1); + } + + if(evt->type == SGL_EVENT_PRESSED) { + sgl_obj_size_zoom(obj, 2); + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_RELEASED) { + sgl_obj_size_zoom(obj, -2); + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a slider object + * @param parent parent object of the slider + * @return slider object + */ +sgl_obj_t* sgl_slider_create(sgl_obj_t* parent) +{ + sgl_slider_t *slider = sgl_malloc(sizeof(sgl_slider_t)); + if(slider == NULL) { + SGL_LOG_ERROR("sgl_slider_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(slider, 0, sizeof(sgl_slider_t)); + + sgl_obj_t *obj = &slider->obj; + sgl_obj_init(&slider->obj, parent); + sgl_obj_set_clickable(obj); + sgl_obj_set_movable(obj); + obj->construct_fn = sgl_slider_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + + slider->direct = SGL_DIRECT_HORIZONTAL; + slider->track_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_BG_COLOR, 128); + slider->knob_color = SGL_THEME_BG_COLOR; + slider->fill_color = SGL_THEME_BG_COLOR; + slider->thickness = 255; + return obj; +} diff --git a/User/system/sgl/widgets/slider/sgl_slider.h b/User/system/sgl/widgets/slider/sgl_slider.h new file mode 100644 index 0000000..252e5e9 --- /dev/null +++ b/User/system/sgl/widgets/slider/sgl_slider.h @@ -0,0 +1,174 @@ +/* source/widgets/sgl_slider.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_SLIDER_H__ +#define __SGL_SLIDER_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl slider struct + * @obj: sgl general object + * @value: slider value + * @desc: slider description + */ +typedef struct sgl_slider { + sgl_obj_t obj; + sgl_color_t track_color; + sgl_color_t knob_color; + sgl_color_t fill_color; + /* 0: horizontal, 1: vertical */ + uint8_t direct : 1; + uint8_t value : 7; + uint8_t thickness; +}sgl_slider_t; + + +/** + * @brief create a slider object + * @param parent parent object of the slider + * @return slider object + */ +sgl_obj_t* sgl_slider_create(sgl_obj_t* parent); + +/** + * @brief set the fill color of the slider + * @param obj slider object + * @param color fill color + * @return none + */ +static inline void sgl_slider_set_fill_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->fill_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the track color of the slider + * @param obj slider object + * @param color track color + * @return none + */ +static inline void sgl_slider_set_track_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->track_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the slider knob color + * @param obj slider object + * @param color knob color + */ +static inline void sgl_slider_set_knob_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->knob_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the slider direction + * @param obj slider object + * @param direct slider direction + * @return none + * @note direct : SGL_DIRECT_HORIZONTAL or SGL_DIRECT_VERTICAL + */ +static inline void sgl_slider_set_direct(sgl_obj_t *obj, uint8_t direct) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->direct = direct; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the slider radius + * @param obj slider object + * @param radius slider radius + * @return none + */ +static inline void sgl_slider_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the slider knob thickness + * @param obj slider object + * @param thickness knob thickness + * @return none + */ +static inline void sgl_slider_set_thickness(sgl_obj_t *obj, uint8_t thickness) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->thickness = sgl_max(thickness, 4); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set the slider value + * @param obj slider object + * @param value slider value + * @return none + */ +static inline void sgl_slider_set_value(sgl_obj_t *obj, uint8_t value) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + slider->value = value; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get the slider value + * @param obj slider object + * @return slider value + */ +static inline uint8_t sgl_slider_get_value(sgl_obj_t *obj) +{ + sgl_slider_t *slider = sgl_container_of(obj, sgl_slider_t, obj); + return slider->value; +} + +/** + * @brief set the slider border width + * @param obj slider object + * @param width border width + */ +static inline void sgl_slider_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_SLIDER_H__ diff --git a/User/system/sgl/widgets/switch/sgl_switch.c b/User/system/sgl/widgets/switch/sgl_switch.c new file mode 100644 index 0000000..0bfc0fc --- /dev/null +++ b/User/system/sgl/widgets/switch/sgl_switch.c @@ -0,0 +1,114 @@ +/* source/widgets/sgl_switch.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgl_switch.h" + + +static void sgl_switch_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_switch_t *p_switch = sgl_container_of(obj, sgl_switch_t, obj); + int16_t margin = p_switch->knob_margin + obj->border; + int16_t radius = sgl_min(obj->radius - margin, p_switch->knob_radius); + int16_t width = obj->coords.y2 - obj->coords.y1 - 2 * margin; + + sgl_rect_t knob_rect = { + .y1 = obj->coords.y1 + margin, + .y2 = obj->coords.y2 - margin, + }; + + sgl_draw_rect_t bg_desc = { + .alpha = p_switch->alpha, + .border = obj->border, + .color = p_switch->color, + .border_color = p_switch->border_color, + .pixmap = p_switch->pixmap, + .radius = obj->radius, + }; + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + if(p_switch->status) { + bg_desc.color = p_switch->color; + knob_rect.x2 = obj->coords.x2 - margin; + knob_rect.x1 = knob_rect.x2 - width; + } + else { + bg_desc.color = p_switch->bg_color; + knob_rect.x1 = obj->coords.x1 + margin; + knob_rect.x2 = knob_rect.x1 + width; + } + + sgl_draw_rect(surf, &obj->area, &obj->coords, &bg_desc); + sgl_draw_fill_rect(surf, &obj->area, &knob_rect, radius, p_switch->knob_color, p_switch->alpha); + } + else if(evt->type == SGL_EVENT_PRESSED) { + p_switch->status = !p_switch->status; + sgl_obj_set_dirty(obj); + } +} + + +/** + * @brief create a switch object + * @param parent parent of the switch + * @return switch object + */ +sgl_obj_t* sgl_switch_create(sgl_obj_t* parent) +{ + sgl_switch_t *p_switch = sgl_malloc(sizeof(sgl_switch_t)); + if(p_switch == NULL) { + SGL_LOG_ERROR("sgl_switch_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(p_switch, 0, sizeof(sgl_switch_t)); + + sgl_obj_t *obj = &p_switch->obj; + sgl_obj_init(&p_switch->obj, parent); + obj->construct_fn = sgl_switch_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + sgl_obj_set_radius(obj, SGL_THEME_RADIUS); + + p_switch->alpha = SGL_THEME_ALPHA; + p_switch->color = SGL_THEME_COLOR; + p_switch->border_color = SGL_THEME_BORDER_COLOR; + + p_switch->status = false; + p_switch->bg_color = SGL_THEME_BG_COLOR; + p_switch->knob_color = sgl_color_mixer(SGL_THEME_COLOR, SGL_THEME_BG_COLOR, 128); + p_switch->knob_radius = 255; + + sgl_obj_set_clickable(obj); + + return obj; +} + diff --git a/User/system/sgl/widgets/switch/sgl_switch.h b/User/system/sgl/widgets/switch/sgl_switch.h new file mode 100644 index 0000000..9e2f8f6 --- /dev/null +++ b/User/system/sgl/widgets/switch/sgl_switch.h @@ -0,0 +1,205 @@ +/* source/widgets/sgl_switch.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_SWITCH_H__ +#define __SGL_SWITCH_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl switch struct + * @obj: sgl general object + * @bg_desc: pointer to sgl_draw_rect_t descriptor + * @knob_desc: pointer to sgl_draw_circle_t descriptor + * @statue: switch status, false: off, true: on + */ +typedef struct sgl_switch { + sgl_obj_t obj; + const sgl_pixmap_t *pixmap; + sgl_color_t border_color; + sgl_color_t color; + sgl_color_t bg_color; + sgl_color_t knob_color; + bool status; + uint8_t alpha; + uint8_t knob_radius; + uint8_t knob_margin; +} sgl_switch_t; + + +/** + * @brief create a switch object + * @param parent parent of the switch + * @return switch object + */ +sgl_obj_t* sgl_switch_create(sgl_obj_t* parent); + + +/** + * @brief set switch color + * @param obj switch object + * @param color switch color + * @return none + */ +static inline void sgl_switch_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set switch background color + * @param obj switch object + * @param color switch background color + * @return none + */ +static inline void sgl_switch_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set the knob color of the switch object + * @param obj Pointer to the switch object + * @param color The color of the knob + * @return none + */ +static inline void sgl_switch_set_knob_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->knob_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set switch alpha + * @param obj switch object + * @param alpha switch alpha + * @return none + */ +static inline void sgl_switch_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set switch radius + * @param obj switch object + * @param radius switch radius + * @return none + */ +static inline void sgl_switch_set_radius(sgl_obj_t *obj, uint16_t radius) +{ + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set switch border color + * @param obj switch object + * @param color switch border color + * @return none + */ +static inline void sgl_switch_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set switch border width + * @param obj switch object + * @param width switch border width + * @return none + */ +static inline void sgl_switch_set_border_width(sgl_obj_t *obj, int16_t width) +{ + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set status of switch + * @param obj switch object + * @param status switch status + * @return none + */ +static inline void sgl_switch_set_status(sgl_obj_t *obj, bool status) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->status = status; + sgl_obj_set_dirty(obj); +} + +/** + * @brief get status of switch + * @param obj switch object + * @return switch status + */ +static inline bool sgl_switch_get_status(sgl_obj_t *obj) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + return switch_obj->status; +} + +/** + * @brief set knob radius of switch + * @param obj switch object + * @param radius knob radius + * @return none + */ +static inline void sgl_switch_set_knob_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->knob_radius = radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set knob margin of switch + * @param obj switch object + * @param margin knob margin + * @return none + */ +static inline void sgl_switch_set_knob_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_switch_t *switch_obj = sgl_container_of(obj, sgl_switch_t, obj); + switch_obj->knob_margin = margin; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_SWITCH_H__ diff --git a/User/system/sgl/widgets/textbox/sgl_textbox.c b/User/system/sgl/widgets/textbox/sgl_textbox.c new file mode 100644 index 0000000..c4279ad --- /dev/null +++ b/User/system/sgl/widgets/textbox/sgl_textbox.c @@ -0,0 +1,155 @@ +/* source/widgets/sgl_textbox.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sgl_textbox.h" + + +#define SGL_TEXTBOX_SCROLL_WIDTH (4) + +static int16_t textbox_scroll_get_pos(sgl_obj_t* obj, int16_t scroll_h) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + int16_t height = obj->coords.y2 - obj->coords.y1 - 2 * textbox->bg.radius; + return (-textbox->y_offset) * (height + scroll_h) / (textbox->text_height - height); +} + + +static void sgl_textbox_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + int16_t height = obj->coords.y2 - obj->coords.y1 - 2 * textbox->bg.radius; + int16_t width = obj->coords.x2 - obj->coords.x1 - 2 * textbox->bg.radius; + int16_t scroll_height = sgl_max(height / 8, SGL_TEXTBOX_SCROLL_WIDTH); + sgl_rect_t area; + + SGL_ASSERT(textbox->font != NULL); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + area.x1 = obj->coords.x1 + textbox->bg.radius; + area.y1 = obj->coords.y1 + textbox->bg.radius; + area.x2 = obj->coords.x2 - textbox->bg.radius; + area.y2 = obj->coords.y2 - textbox->bg.radius; + + sgl_draw_rect(surf, &obj->area, &obj->coords, &textbox->bg); + sgl_draw_string_mult_line(surf, &area, area.x1, + area.y1 + textbox->y_offset, + textbox->text, textbox->text_color, textbox->bg.alpha, textbox->font, textbox->line_margin + ); + + if(textbox->scroll_enable) { + area.x1 = obj->coords.x2 - SGL_TEXTBOX_SCROLL_WIDTH - textbox->bg.radius; + area.y1 = obj->coords.y1; + area.x2 = obj->coords.x2 - textbox->bg.radius; + area.y2 = obj->coords.y2; + + area.y1 = textbox_scroll_get_pos(obj, scroll_height) + obj->coords.y1; + area.y2 = area.y1 + scroll_height; + + sgl_draw_fill_rect(surf, &obj->area, &area, SGL_TEXTBOX_SCROLL_WIDTH / 2, textbox->text_color, 128); + } + } + else if(evt->type == SGL_EVENT_MOVE_UP) { + textbox->text_height = sgl_font_get_string_height(width, textbox->text, textbox->font, textbox->line_margin); + textbox->scroll_enable = 1; + if((textbox->text_height + textbox->y_offset) > height ) { + textbox->y_offset -= evt->distance; + } + sgl_obj_set_dirty(obj); + } + else if(evt->type == SGL_EVENT_MOVE_DOWN) { + textbox->text_height = sgl_font_get_string_height(width, textbox->text, textbox->font, textbox->line_margin); + textbox->scroll_enable = 1; + if(textbox->y_offset < 0) { + textbox->y_offset += evt->distance; + } + sgl_obj_set_dirty(obj); + } + else if (evt->type == SGL_EVENT_PRESSED) { + textbox->scroll_enable = 1; + sgl_obj_set_dirty(obj); + } + else if (evt->type == SGL_EVENT_RELEASED) { + textbox->scroll_enable = 0; + sgl_obj_set_dirty(obj); + } + else if (evt->type == SGL_EVENT_FOCUSED) { + textbox->bg.border ++; + } + else if (evt->type == SGL_EVENT_UNFOCUSED) { + textbox->bg.border --; + } +} + + +/** + * @brief create a textbox object + * @param parent parent of the textbox + * @return pointer to the textbox object + */ +sgl_obj_t* sgl_textbox_create(sgl_obj_t* parent) +{ + sgl_textbox_t *textbox = sgl_malloc(sizeof(sgl_textbox_t)); + if(textbox == NULL) { + SGL_LOG_ERROR("sgl_textbox_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(textbox, 0, sizeof(sgl_textbox_t)); + + sgl_obj_t *obj = &textbox->obj; + sgl_obj_init(&textbox->obj, parent); + obj->construct_fn = sgl_textbox_construct_cb; + sgl_obj_set_border_width(obj, SGL_THEME_BORDER_WIDTH); + obj->focus = 1; + + sgl_obj_set_clickable(obj); + sgl_obj_set_movable(obj); + + textbox->bg.alpha = SGL_THEME_ALPHA; + textbox->bg.color = SGL_THEME_COLOR; + textbox->bg.radius = 10; + textbox->bg.border = 1; + textbox->bg.border_color = SGL_THEME_BORDER_COLOR; + textbox->font = sgl_get_system_font(); + + textbox->scroll.alpha = SGL_THEME_ALPHA; + textbox->scroll.color = SGL_THEME_SCROLL_FG_COLOR; + + textbox->text_color = SGL_THEME_TEXT_COLOR; + textbox->line_margin = 1; + textbox->text = "textbox"; + + textbox->y_offset = 0; + textbox->scroll_enable = 0; + + return obj; +} diff --git a/User/system/sgl/widgets/textbox/sgl_textbox.h b/User/system/sgl/widgets/textbox/sgl_textbox.h new file mode 100644 index 0000000..01be927 --- /dev/null +++ b/User/system/sgl/widgets/textbox/sgl_textbox.h @@ -0,0 +1,182 @@ +/* source/widgets/sgl_textbox.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_TEXTBOX_H__ +#define __SGL_TEXTBOX_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl textbox struct + * @desc: text description + */ +typedef struct sgl_textbox { + sgl_obj_t obj; + sgl_draw_rect_t bg; + const char *text; + const sgl_font_t *font; + uint8_t line_margin; + sgl_color_t text_color; + int32_t y_offset; + sgl_draw_rect_t scroll; + uint32_t text_height: 31; + uint32_t scroll_enable: 1; +}sgl_textbox_t; + + +/** + * @brief create a textbox object + * @param parent parent of the textbox + * @return textbox object + */ +sgl_obj_t* sgl_textbox_create(sgl_obj_t* parent); + + +/** + * @brief set text of the textbox + * @param obj textbox object + * @param text text to be set + */ +static inline void sgl_textbox_set_text(sgl_obj_t *obj, const char *text) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set text color of the textbox + * @param obj textbox object + * @param color text color to be set + * @return none + */ +static inline void sgl_textbox_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set text font of the textbox + * @param obj textbox object + * @param font font of text + * @return none + */ +static inline void sgl_textbox_set_text_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set background color of the textbox + * @param obj textbox object + * @param color background color to be set + * @return none + */ +static inline void sgl_textbox_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->bg.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set radius of the textbox + * @param obj textbox object + * @param radius radius to be set + * @return none + */ +static inline void sgl_textbox_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + sgl_obj_set_radius(obj, radius); + textbox->bg.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set border color of the textbox + * @param obj textbox object + * @param color border color to be set + * @return none + */ +static inline void sgl_textbox_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->bg.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set border width of the textbox + * @param obj textbox object + * @param width border width to be set + * @return none + */ +static inline void sgl_textbox_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->bg.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textbox pixmap + * @param obj textbox object + * @param pixmap pixmap to be set + * @return none + */ +static inline void sgl_textbox_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->bg.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textbox line margin + * @param obj textbox object + * @param margin line margin to be set + * @return none + */ +static inline void sgl_textbox_set_line_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_textbox_t *textbox = sgl_container_of(obj, sgl_textbox_t, obj); + textbox->line_margin = margin; + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_TEXTBOX_H__ diff --git a/User/system/sgl/widgets/textline/sgl_textline.c b/User/system/sgl/widgets/textline/sgl_textline.c new file mode 100644 index 0000000..0e5c176 --- /dev/null +++ b/User/system/sgl/widgets/textline/sgl_textline.c @@ -0,0 +1,88 @@ +/* source/widgets/sgl_textline.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sgl_textline.h" + + +static void sgl_textline_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + sgl_area_t text_area; + SGL_ASSERT(textline->font != NULL); + + if(evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_obj_set_height(obj, sgl_font_get_string_height(obj->coords.x2 - obj->coords.x1 + 1, textline->text, textline->font, textline->line_margin) + obj->radius * 2); + sgl_area_clip(&obj->parent->area, &obj->coords, &obj->area); + + text_area.x1 = obj->coords.x1 + obj->radius; + text_area.x2 = obj->coords.x2 - obj->radius; + text_area.y1 = obj->coords.y1 + obj->radius; + text_area.y2 = obj->coords.y2 - obj->radius; + + if (textline->bg_flag) { + sgl_draw_fill_rect(surf, &obj->area, &obj->coords, obj->radius, textline->bg_color, textline->alpha); + } + + sgl_draw_string_mult_line(surf, &text_area, obj->coords.x1 + obj->radius, obj->coords.y1 + obj->radius, textline->text, textline->color, textline->alpha, textline->font, textline->line_margin); + } +} + + +/** + * @brief create a textline object + * @param parent parent of the textline + * @return pointer to the textline object + */ +sgl_obj_t* sgl_textline_create(sgl_obj_t* parent) +{ + sgl_textline_t *textline = sgl_malloc(sizeof(sgl_textline_t)); + if(textline == NULL) { + SGL_LOG_ERROR("sgl_textline_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(textline, 0, sizeof(sgl_textline_t)); + + sgl_obj_t *obj = &textline->obj; + sgl_obj_init(&textline->obj, parent); + obj->construct_fn = sgl_textline_construct_cb; + + textline->alpha = SGL_THEME_ALPHA; + textline->bg_flag = true; + textline->bg_color = SGL_THEME_COLOR; + textline->color = SGL_THEME_TEXT_COLOR; + textline->line_margin = 1; + textline->text = "textline"; + textline->font = sgl_get_system_font(); + + return obj; +} diff --git a/User/system/sgl/widgets/textline/sgl_textline.h b/User/system/sgl/widgets/textline/sgl_textline.h new file mode 100644 index 0000000..1b3a4b8 --- /dev/null +++ b/User/system/sgl/widgets/textline/sgl_textline.h @@ -0,0 +1,169 @@ +/* source/widgets/sgl_textline.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_TEXTLINE_H__ +#define __SGL_TEXTLINE_H__ + +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief sgl textline struct + * @desc: text description + */ +typedef struct sgl_textline { + sgl_obj_t obj; + const char *text; + const sgl_font_t *font; + sgl_color_t color; + sgl_color_t bg_color; + uint8_t line_margin; + uint8_t edge_margin : 7; + uint8_t bg_flag : 1; + uint8_t alpha; +} sgl_textline_t; + + +/** + * @brief create a textline object + * @param parent parent of the textline + * @return textline object + */ +sgl_obj_t* sgl_textline_create(sgl_obj_t* parent); + + +/** + * @brief set textline text + * @param obj textline object + * @param text text + * @return none + */ +static inline void sgl_textline_set_text(sgl_obj_t *obj, const char *text) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->text = text; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline font + * @param obj textline object + * @param font font + * @return none + */ +static inline void sgl_textline_set_text_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline text color + * @param obj textline object + * @param color color of text + * @return none + */ +static inline void sgl_textline_set_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline background color + * @param obj textline object + * @param color color of background + * @return none + */ +static inline void sgl_textline_set_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->bg_color = color; + textline->bg_flag = true; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline radius + * @param obj textline object + * @param radius radius of textline + * @return none + */ +static inline void sgl_textline_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + sgl_obj_set_radius(obj, radius); + textline->obj.radius = obj->radius; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline alpha + * @param obj textline object + * @param alpha alpha of textline + * @return none + */ +static inline void sgl_textline_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline edge margin + * @param obj textline object + * @param margin margin of textline + * @return none + */ +static inline void sgl_textline_set_edge_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->edge_margin = margin; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set textline text line margin + * @param obj textline object + * @param margin margin of textline + * @return none + */ +static inline void sgl_textline_set_line_margin(sgl_obj_t *obj, uint8_t margin) +{ + sgl_textline_t *textline = sgl_container_of(obj, sgl_textline_t, obj); + textline->line_margin = margin; + sgl_obj_set_dirty(obj); +} + + +#endif // !__SGL_TEXTLINE_H__ diff --git a/User/system/sgl/widgets/unzip_image/sgl_unzip_image.c b/User/system/sgl/widgets/unzip_image/sgl_unzip_image.c new file mode 100644 index 0000000..5275692 --- /dev/null +++ b/User/system/sgl/widgets/unzip_image/sgl_unzip_image.c @@ -0,0 +1,237 @@ +/* source/widgets/img/sgl_unzip_img.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * This module is ported from the unzipping code of the open-source project + * SC_GUI (Project URL: https://gitee.com/li_yucheng/scgui, Author Contact: QQ 617622104). + * We sincerely appreciate the author's open-source spirit and selfless sharing. + */ + +#include +#include +#include +#include +#include +#include +#include "sgl_unzip_image.h" + +/** + * @brief Compressed image decoder structure + */ +typedef struct { + uint32_t n; /* Current decode position */ + int16_t x; /* Current X coordinate */ + int16_t y; /* Current Y coordinate */ + uint16_t rep_cnt; /* Repeat count */ + sgl_color_t out; /* Output color value */ + sgl_color_t unzip; /* Unzip buffer */ + const uint8_t *p; /* Image data pointer */ +} sgl_unzip_img_dec_t; + +/** + * @brief Initialize compressed image decoder + * @param dec Decoder structure pointer + * @param unzip_img Compressed image data + */ +static void sgl_unzip_img_dec_init(sgl_unzip_img_dec_t *dec, const sgl_unzip_img_pixmap_t *unzip_img) +{ + SGL_ASSERT(dec != NULL); + SGL_ASSERT(unzip_img != NULL); + + dec->n = 0; + dec->x = 0; + dec->y = 0; + dec->rep_cnt = 0; + dec->out = sgl_int2color(0); + dec->unzip = sgl_int2color(0); + dec->p = unzip_img->map; +} + +/** + * @brief Incrementally decompress compressed image data + * @param dec Decoder pointer + */ +static void sgl_unzip_img_incremental(sgl_unzip_img_dec_t *dec) +{ + if (dec->rep_cnt == 0) { + dec->rep_cnt = 1; + if (dec->p[dec->n] & 0x20) { + sgl_color_t dat16; + dat16 = sgl_int2color(dec->p[dec->n] | (dec->p[dec->n + 1] << 8)); + if (sgl_color2int(dec->unzip) == sgl_color2int(dat16)) { + dec->n += 2; + dec->rep_cnt = (dec->p[dec->n] << 8) | dec->p[dec->n + 1]; + } else { + dec->unzip = dat16; + dec->out = dat16; + } + dec->n += 2; + } else { + uint8_t b = dec->p[dec->n]; + uint16_t r = (b << 5) & 0x1800; + uint16_t g = (b << 3) & 0x00e3; + dec->out = sgl_int2color((sgl_color2int(dec->unzip) ^ (r + g + (b & 0x03)))); + dec->n++; + } + } +} + + +/** + * @brief Draw compressed image with transparency + * @param surf Drawing surface + * @param xs Starting X coordinate + * @param ys Starting Y coordinate + * @param unzip_img Compressed image data + * @param color Color (for color replacement) + * @param alpha Transparency + */ +static void sgl_draw_unzip_img_with_alpha(sgl_surf_t *surf, int16_t xs, int16_t ys, + const sgl_unzip_img_pixmap_t *unzip_img, sgl_color_t color, uint8_t alpha) +{ + SGL_ASSERT(surf != NULL); + SGL_ASSERT(unzip_img != NULL); + + SGL_UNUSED(color); + + sgl_area_t img_rect; + img_rect.x1 = xs; + img_rect.y1 = ys; + img_rect.x2 = xs + unzip_img->width - 1; + img_rect.y2 = ys + unzip_img->height - 1; + + sgl_area_t intersection; + if (!sgl_surf_clip(surf, &img_rect, &intersection)) { + return; + } + + sgl_unzip_img_dec_t dec; + sgl_unzip_img_dec_init(&dec, unzip_img); + + // int16_t xe = xs + unzip_img->width - 1; + int16_t ye = ys + unzip_img->height - 1; + + while (dec.y <= ye && dec.y <= intersection.y2) { + sgl_unzip_img_incremental(&dec); + while (dec.rep_cnt > 0) { + dec.rep_cnt--; + int16_t x = xs + dec.x; + int16_t y = ys + dec.y; + + if (x >= intersection.x1 && x <= intersection.x2 && + y >= intersection.y1 && y <= intersection.y2) { + sgl_color_t *buf = sgl_surf_get_buf(surf, x - surf->x1, y - surf->y1); + *buf = sgl_color_mixer(dec.out, *buf, alpha); + // For monochrome images, can be used to change image color + // if (buf != NULL) { + // if (sgl_color2int(color) != 0) { + // *buf = sgl_color_mixer(color, *buf, alpha); + // } else { + // *buf = sgl_color_mixer(dec.out, *buf, alpha); + // } + // } + } + + if (++dec.x >= unzip_img->width) { + dec.x = 0; + if (++dec.y > ye) { + break; + } + } + } + } +} + +/** + * @brief Draw compressed image + * @param surf Drawing surface + * @param area Clipping area + * @param coords Object coordinates + * @param desc Drawing description + */ +void sgl_draw_unzip_img(sgl_surf_t *surf, sgl_rect_t *area, sgl_rect_t *coords, sgl_draw_unzip_img_t *desc) +{ + SGL_ASSERT(surf != NULL); + SGL_ASSERT(desc != NULL); + SGL_ASSERT(desc->unzip_img != NULL); + + SGL_UNUSED(area); + + int16_t xs = coords->x1; + int16_t ys = coords->y1; + + if (SGL_ALPHA_MIN == desc->alpha) { + return; + } else { + sgl_draw_unzip_img_with_alpha(surf, xs, ys, desc->unzip_img, desc->color, desc->alpha); + } +} + + +/** + * @brief Compressed image construction callback + * @param surf Drawing surface + * @param obj Object pointer + * @param evt Event pointer + */ +static void sgl_unzip_img_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_unzip_img_t *unzip_img = (sgl_unzip_img_t*)obj; + + if (evt->type == SGL_EVENT_DRAW_MAIN) { + if (unzip_img->desc.unzip_img != NULL) { + sgl_draw_unzip_img(surf, &obj->area, &obj->coords, &unzip_img->desc); + } + } + else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_RELEASED) { + if (obj->event_fn) { + obj->event_fn(evt); + } + } +} + +/** + * @brief Create compressed image object + * @param parent Parent object pointer + * @return Object pointer + */ +sgl_obj_t* sgl_unzip_img_create(sgl_obj_t* parent) +{ + sgl_unzip_img_t *unzip_img = sgl_malloc(sizeof(sgl_unzip_img_t)); + if (unzip_img == NULL) { + SGL_LOG_ERROR("sgl_unzip_img_create: malloc failed"); + return NULL; + } + + memset(unzip_img, 0, sizeof(sgl_unzip_img_t)); + + sgl_obj_t *obj = &unzip_img->obj; + sgl_obj_init(obj, parent); + obj->construct_fn = sgl_unzip_img_construct_cb; + + unzip_img->desc.alpha = 255; + unzip_img->desc.unzip_img = NULL; + unzip_img->desc.color = sgl_int2color(0); + unzip_img->desc.align = SGL_ALIGN_CENTER; + + return obj; +} diff --git a/User/system/sgl/widgets/unzip_image/sgl_unzip_image.h b/User/system/sgl/widgets/unzip_image/sgl_unzip_image.h new file mode 100644 index 0000000..191fb8b --- /dev/null +++ b/User/system/sgl/widgets/unzip_image/sgl_unzip_image.h @@ -0,0 +1,124 @@ +/* source/widgets/img/sgl_unzip_img.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: https://sgl-docs.readthedocs.io + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * This module is ported from the unzipping code of the open-source project + * SC_GUI (Project URL: https://gitee.com/li_yucheng/scgui, Author Contact: QQ 617622104). + * We sincerely appreciate the author's open-source spirit and selfless sharing. + */ + +#ifndef __SGL_UNZIP_IMAGE_H__ +#define __SGL_UNZIP_IMAGE_H__ + +#include +#include + +/** + * @brief Compressed image data structure + */ +typedef struct { + uint16_t width; // Image width + uint16_t height; // Image height + const uint8_t *map; // Compressed image data +} sgl_unzip_img_pixmap_t; + +/** + * @brief Compressed image drawing description + */ +typedef struct { + const sgl_unzip_img_pixmap_t *unzip_img; // Compressed image data + sgl_color_t color; // Image color + uint8_t alpha; // Transparency + sgl_align_type_t align; // Alignment type +} sgl_draw_unzip_img_t; + +/** + * @brief Compressed image object + */ +typedef struct { + sgl_obj_t obj; // Base object + sgl_draw_unzip_img_t desc; // Drawing description +} sgl_unzip_img_t; + +/** + * @brief Create compressed image object + * @param parent Parent object + * @return Created image object pointer + */ +sgl_obj_t* sgl_unzip_img_create(sgl_obj_t *parent); + +/** + * @brief Set image color + * @param obj Image object pointer + * @param color Image color + * @return none + */ +static inline void sgl_unzip_img_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_unzip_img_t *img = sgl_container_of(obj, sgl_unzip_img_t, obj); + img->desc.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set image alpha value + * @param obj Image object pointer + * @param alpha Image alpha value + * @return none + */ +static inline void sgl_unzip_img_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_unzip_img_t *img = sgl_container_of(obj, sgl_unzip_img_t, obj); + img->desc.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set image alignment type + * @param obj Image object pointer + * @param align Image alignment type + * @return none + */ +static inline void sgl_unzip_img_set_align(sgl_obj_t *obj, sgl_align_type_t align) +{ + sgl_unzip_img_t *img = sgl_container_of(obj, sgl_unzip_img_t, obj); + img->desc.align = align; + sgl_obj_set_dirty(obj); +} + +/** + * @brief Set image compressed image data + * @param obj Image object pointer + * @param unzip_img Compressed image data + * @return none + */ +static inline void sgl_unzip_img_set_img(sgl_obj_t *obj, const sgl_unzip_img_pixmap_t *unzip_img) +{ + sgl_unzip_img_t *img = sgl_container_of(obj, sgl_unzip_img_t, obj); + img->desc.unzip_img = unzip_img; + if (img->desc.unzip_img != NULL) { + sgl_obj_set_size(obj, img->desc.unzip_img->width, img->desc.unzip_img->height); + } + sgl_obj_set_dirty(obj); +} + +#endif /* __SGL_UNZIP_IMAGE_H__ */ diff --git a/User/system/sgl/widgets/win/sgl_win.c b/User/system/sgl/widgets/win/sgl_win.c new file mode 100644 index 0000000..295d580 --- /dev/null +++ b/User/system/sgl/widgets/win/sgl_win.c @@ -0,0 +1,102 @@ +/* source/widgets/sgl_win.c + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include "sgl_win.h" + +static void sgl_win_construct_cb(sgl_surf_t *surf, sgl_obj_t* obj, sgl_event_t *evt) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + sgl_rect_t bg = obj->coords; + sgl_rect_t title_bg = obj->coords; + sgl_pos_t align_pos; + int16_t close_cx, close_cy, close_r, title_h; + + win->title_h = sgl_max3(obj->radius, win->title_h, sgl_font_get_height(win->title_font)); + title_h = win->title_h; + //bg.y1 -= title_h; + title_bg.y1 = bg.y1; + title_bg.y2 = title_bg.y1 + title_h; + close_r = title_h / 3; + close_cx = obj->coords.x2 - close_r - obj->radius / 2; + close_cy = title_bg.y1 + title_h / 2 + obj->border / 2; + + if (evt->type == SGL_EVENT_DRAW_MAIN) { + sgl_draw_rect(surf, &obj->area, &bg, &win->bg); + sgl_draw_fill_rect_with_border(surf, &title_bg, &bg, obj->radius, win->title_bg_color, + win->bg.border_color, win->bg.border, win->bg.alpha + ); + + align_pos = sgl_get_text_pos(&title_bg, win->title_font, win->title_text, 0, (sgl_align_type_t)win->title_align); + if (win->title_align == SGL_ALIGN_LEFT_MID) { + align_pos.x += obj->radius; + } + sgl_draw_string(surf, &obj->area, align_pos.x, align_pos.y + obj->border, win->title_text, + win->title_text_color, win->bg.alpha, win->title_font + ); + + sgl_draw_fill_circle(surf, &title_bg, close_cx, close_cy, close_r, win->close_color, win->bg.alpha); + } + else if (evt->type == SGL_EVENT_PRESSED || evt->type == SGL_EVENT_CLICKED) { + if (evt->pos.x >= (close_cx - close_r) && evt->pos.x <= (close_cx + close_r) + && evt->pos.y >= (close_cy - close_r) && evt->pos.y <= (close_cy + close_r)) { + sgl_obj_set_destroyed(obj); + } + } +} + +/** + * @brief create a window object + * @param parent parent of the window + * @return window object + */ +sgl_obj_t* sgl_win_create(sgl_obj_t* parent) +{ + sgl_win_t *win = sgl_malloc(sizeof(sgl_win_t)); + if(win == NULL) { + SGL_LOG_ERROR("sgl_win_create: malloc failed"); + return NULL; + } + + /* set object all member to zero */ + memset(win, 0, sizeof(sgl_win_t)); + + sgl_obj_t *obj = &win->obj; + sgl_obj_init(&win->obj, parent); + obj->construct_fn = sgl_win_construct_cb; + sgl_obj_set_clickable(obj); + + win->bg.alpha = SGL_THEME_ALPHA; + win->bg.color = SGL_THEME_COLOR; + win->bg.radius = SGL_THEME_RADIUS; + win->bg.border = 0; + win->bg.border_color = SGL_THEME_BORDER_COLOR; + + win->title_align = SGL_ALIGN_LEFT_MID; + win->title_bg_color = SGL_THEME_COLOR; + win->title_font = sgl_get_system_font(); + win->close_color = sgl_rgb(255, 90, 80); + + return obj; +} diff --git a/User/system/sgl/widgets/win/sgl_win.h b/User/system/sgl/widgets/win/sgl_win.h new file mode 100644 index 0000000..77ce21a --- /dev/null +++ b/User/system/sgl/widgets/win/sgl_win.h @@ -0,0 +1,214 @@ +/* source/widgets/sgl_win.h + * + * MIT License + * + * Copyright(c) 2023-present All contributors of SGL + * Document reference link: docs directory + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __SGL_WIN_H__ +#define __SGL_WIN_H__ + +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief sgl window struct + * @obj: sgl general object + */ +typedef struct sgl_win { + sgl_obj_t obj; + const char *title_text; + const sgl_font_t *title_font; + sgl_color_t title_bg_color; + sgl_color_t title_text_color; + sgl_draw_rect_t bg; + uint8_t title_h; + uint8_t title_align; + sgl_color_t close_color; +} sgl_win_t; + +/** + * @brief create a window object + * @param parent parent of the window + * @return window object + */ +sgl_obj_t* sgl_win_create(sgl_obj_t* parent); + +static inline void sgl_win_set_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window radius + * @param obj window object + * @param radius radius + */ +static inline void sgl_win_set_radius(sgl_obj_t *obj, uint8_t radius) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.radius = radius; + sgl_obj_set_radius(obj, radius); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window alpha + * @param obj window object + * @param alpha alpha + */ +static inline void sgl_win_set_alpha(sgl_obj_t *obj, uint8_t alpha) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.alpha = alpha; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window border width + * @param obj window object + * @param width border width + */ +static inline void sgl_win_set_border_width(sgl_obj_t *obj, uint8_t width) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.border = width; + sgl_obj_set_border_width(obj, width); + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window border color + * @param obj window object + * @param color border color + */ +static inline void sgl_win_set_border_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.border_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window pixmap + * @param obj window object + * @param pixmap pixmap + */ +static inline void sgl_win_set_pixmap(sgl_obj_t *obj, const sgl_pixmap_t *pixmap) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->bg.pixmap = pixmap; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window title text + * @param obj window object + * @param text title text + */ +static inline void sgl_win_set_title_text(sgl_obj_t *obj, const char *text) +{ + sgl_area_t area = obj->area; + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_text = text; + area.y2 = area.y1 + win->title_h; + sgl_obj_update_area(&area); +} + +/** + * @brief set window title text color + * @param obj window object + * @param color text color + */ +static inline void sgl_win_set_title_text_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_text_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window title font + * @param obj window object + * @param font title font + */ +static inline void sgl_win_set_title_font(sgl_obj_t *obj, const sgl_font_t *font) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_font = font; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window title height + * @param obj window object + * @param height title height + */ +static inline void sgl_win_set_title_height(sgl_obj_t *obj, uint16_t height) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_h = height; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window title text align + * @param obj window object + * @param align text align + */ +static inline void sgl_win_set_title_text_align(sgl_obj_t *obj, uint8_t align) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_align = align; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window title background color + * @param obj window object + * @param color title background color + */ +static inline void sgl_win_set_title_bg_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->title_bg_color = color; + sgl_obj_set_dirty(obj); +} + +/** + * @brief set window close button color + * @param obj window object + * @param color close button color + */ +static inline void sgl_win_set_close_btn_color(sgl_obj_t *obj, sgl_color_t color) +{ + sgl_win_t *win = sgl_container_of(obj, sgl_win_t, obj); + win->close_color = color; + sgl_obj_set_dirty(obj); +} + +#endif // !__SGL_LED_H__