From b53fa53389f2fd52bb3ffb7fa03903b0ebc501e1 Mon Sep 17 00:00:00 2001 From: Shuanglei Tao Date: Mon, 13 Oct 2025 08:30:37 +0800 Subject: [PATCH] update gui layout --- GUI/Adafruit_GFX.c | 98 ++++++++++++++++++++++++++ GUI/Adafruit_GFX.h | 4 ++ GUI/GUI.c | 116 +++++++++++++++++++------------ GUI/GUI.h | 4 -- GUI/fonts.c | 166 ++++++++++++++++++++++++++++++++++++++++++--- GUI/fonts.h | 5 -- Makefile.win32 | 2 +- 7 files changed, 329 insertions(+), 66 deletions(-) diff --git a/GUI/Adafruit_GFX.c b/GUI/Adafruit_GFX.c index 468c334..05ec1f2 100644 --- a/GUI/Adafruit_GFX.c +++ b/GUI/Adafruit_GFX.c @@ -359,6 +359,71 @@ void GFX_drawLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t } } } + +/**************************************************************************/ +/*! + @brief Draw a dotted line. Bresenham's algorithm - thx wikpedia + @param x0 Start point x coordinate + @param y0 Start point y coordinate + @param x1 End point x coordinate + @param y1 End point y coordinate + @param color 16-bit 5-6-5 Color to draw with +*/ +/**************************************************************************/ +void GFX_drawDottedLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, + uint16_t color, uint8_t dot_len, uint8_t space_len) { + int16_t steep = ABS(y1 - y0) > ABS(x1 - x0); + if (steep) { + SWAP(x0, y0, int16_t); + SWAP(x1, y1, int16_t); + } + + if (x0 > x1) { + SWAP(x0, x1, int16_t); + SWAP(y0, y1, int16_t); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = ABS(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + uint8_t draw = 1; + uint8_t len = 0; + for (; x0 <= x1; x0++) { + if (draw) { + if (steep) { + GFX_drawPixel(gfx, y0, x0, color); + } else { + GFX_drawPixel(gfx, x0, y0, color); + } + len++; + if (len >= dot_len) { + len = 0; + draw = 0; + } + } else { + len++; + if (len >= space_len) { + len = 0; + draw = 1; + } + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} /**************************************************************************/ /*! @@ -860,6 +925,10 @@ int8_t GFX_getFontDescent(Adafruit_GFX *gfx) { return gfx->u8g2.font_info.descent_g; } +int8_t GFX_getFontHeight(Adafruit_GFX *gfx) { + return gfx->u8g2.font_info.ascent_A - gfx->u8g2.font_info.descent_g; +} + int16_t GFX_drawGlyph(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t e) { return u8g2_DrawGlyph(&gfx->u8g2, x, y, e); } @@ -992,6 +1061,35 @@ int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str) return w; } +int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...) +{ + char buf[64] = {0}; + char *str = buf; + size_t len; + va_list va; + + va_start(va, format); + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + + if (len > sizeof(buf) - 1) + { + str = malloc(len + 1); + if (str == NULL) + return 0; + va_start(va, format); + vsnprintf(str, len + 1, format, va); + va_end(va); + } + + int16_t w = GFX_getUTF8Width(gfx, str); + + if (str != buf) + free(str); + + return w; +} + size_t GFX_print(Adafruit_GFX *gfx, const char c) { int16_t delta; uint16_t e = utf8_next(gfx, (uint8_t)c); diff --git a/GUI/Adafruit_GFX.h b/GUI/Adafruit_GFX.h index c09e5b1..8a05c5b 100644 --- a/GUI/Adafruit_GFX.h +++ b/GUI/Adafruit_GFX.h @@ -57,6 +57,8 @@ void GFX_end(Adafruit_GFX *gfx); // DRAW API void GFX_drawPixel(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t color); void GFX_drawLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color); +void GFX_drawDottedLine(Adafruit_GFX *gfx, int16_t x0, int16_t y0, int16_t x1, int16_t y1, + uint16_t color, uint8_t dot_len, uint8_t space_len); void GFX_drawFastVLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t h, uint16_t color); void GFX_drawFastHLine(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, uint16_t color); void GFX_fillRect(Adafruit_GFX *gfx, int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); @@ -87,10 +89,12 @@ void GFX_setFontDirection(Adafruit_GFX *gfx, GFX_Rotate d); void GFX_setTextColor(Adafruit_GFX *gfx, uint16_t fg, uint16_t bg); int8_t GFX_getFontAscent(Adafruit_GFX *gfx); int8_t GFX_getFontDescent(Adafruit_GFX *gfx); +int8_t GFX_getFontHeight(Adafruit_GFX *gfx); int16_t GFX_drawGlyph(Adafruit_GFX *gfx, int16_t x, int16_t y, uint16_t e); int16_t GFX_drawStr(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *s); int16_t GFX_drawUTF8(Adafruit_GFX *gfx, int16_t x, int16_t y, const char *str); int16_t GFX_getUTF8Width(Adafruit_GFX *gfx, const char *str); +int16_t GFX_getUTF8Widthf(Adafruit_GFX *gfx, const char* format, ...); size_t GFX_print(Adafruit_GFX *gfx, const char c); size_t GFX_write(Adafruit_GFX *gfx, const char *buffer, size_t size); size_t GFX_printf(Adafruit_GFX *gfx, const char* format, ...); diff --git a/GUI/GUI.c b/GUI/GUI.c index f3a24a1..9b65b92 100644 --- a/GUI/GUI.c +++ b/GUI/GUI.c @@ -144,10 +144,10 @@ static void DrawTimeSyncTip(Adafruit_GFX *gfx, gui_data_t *data) GFX_fillRect(gfx, box_x, box_y, box_w, box_h, GFX_WHITE); GFX_drawRoundRect(gfx, box_x, box_y, box_w, box_h, 5, GFX_BLACK); GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); - GFX_setCursor(gfx, box_x + (box_w - GFX_getUTF8Width(gfx, title)) / 2, 145); + GFX_setCursor(gfx, box_x + (box_w - GFX_getUTF8Width(gfx, title)) / 2, box_y + 20); GFX_printf(gfx, title); GFX_setTextColor(gfx, GFX_BLACK, GFX_WHITE); - GFX_setCursor(gfx, box_x + 10, 164); + GFX_setCursor(gfx, box_x + 10, box_y + 35); GFX_printf(gfx, url); } @@ -204,23 +204,25 @@ static void DrawDateHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, st GFX_printf(gfx, " [%s]", Lunar_ZodiacString[LUNAR_GetZodiac(Lunar)]); GFX_setTextColor(gfx, GFX_BLACK, GFX_WHITE); - DrawBattery(gfx, data->width - 10 - 2, 6, 20, data->voltage); + DrawBattery(gfx, data->width - 10 - 2, data->height > 300 ? 16 : 6, 20, data->voltage); GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, data->ssid) - 10, y); GFX_printf(gfx, "%s", data->ssid); } static void DrawWeekHeader(Adafruit_GFX *gfx, int16_t x, int16_t y, gui_data_t *data) { - GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); + GFX_setFont(gfx, data->height > 300 ? u8g2_font_wqy12_t_lunar : u8g2_font_wqy9_t_lunar); uint8_t w = (data->width - 2 * x) / 7; + uint8_t h = data->height > 300 ? 32 : 24; uint8_t r = (data->width - 2 * x) % 7; + uint8_t fh = (h - GFX_getFontHeight(gfx)) / 2 + GFX_getFontAscent(gfx) + 1; int16_t cw = GFX_getUTF8Width(gfx, Lunar_DayString[0]); for (int i = 0; i < 7; i++) { uint8_t day = (data->week_start + i) % 7; uint16_t bg = (day == 0 || day == 6) ? GFX_RED : GFX_BLACK; - GFX_fillRect(gfx, x + i * w, y, i == 6 ? (w + r) : w, 24, bg); + GFX_fillRect(gfx, x + i * w, y, i == 6 ? (w + r) : w, h, bg); GFX_setTextColor(gfx, GFX_WHITE, bg); - GFX_setCursor(gfx, x + (w - cw) / 2 + i * w, y + 16); + GFX_setCursor(gfx, x + (w - cw) / 2 + i * w, y + fh); GFX_printf(gfx, "%s", Lunar_DayString[day]); } } @@ -234,6 +236,14 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str int16_t bw = (data->width - x - 10) / 7; int16_t bh = (data->height - y - 10) / monthDayRows; + bool large = data->height > 300; + + if (large) { + for (uint8_t i = 1; i < monthDayRows; i++) + GFX_drawDottedLine(gfx, x, y + i * bh, x + 7 * bw - 1, y + i * bh, GFX_BLACK, 1, 5); + for (uint8_t i = 1; i < 7; i++) + GFX_drawDottedLine(gfx, x + i * bw, y, x + i * bw, y + monthDayRows * bh - 1, GFX_BLACK, 1, 5); + } for (uint8_t i = 0; i < monthMaxDays; i++) { uint16_t year = tm->tm_year + YEAR0; @@ -244,45 +254,49 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str int16_t displayWeek = (adjustedFirstDay + i) % 7; bool weekend = (actualWeek == 0) || (actualWeek == 6); - int16_t bx = x + 16 + displayWeek * bw; - int16_t by = y + 20 + (i + adjustedFirstDay) / 7 * (monthDayRows > 5 ? bh - 1 : bh); + LUNAR_SolarToLunar(Lunar, year, month, day); + + int16_t cr = large ? 13 : 10; + int16_t bx = x + (bw - 2 * cr) / 2 + displayWeek * bw; + int16_t by = y + (bh - 2 * cr) / 2 + (i + adjustedFirstDay) / 7 * bh + 3; if (day == tm->tm_mday) { - GFX_fillCircle(gfx, bx + 11, by + 11, 22, GFX_RED); + GFX_fillCircle(gfx, bx + cr, by + cr - 3, 2 * cr, GFX_RED); GFX_setTextColor(gfx, GFX_WHITE, GFX_RED); } else { GFX_setTextColor(gfx, weekend ? GFX_RED : GFX_BLACK, GFX_WHITE); } - GFX_setFont(gfx, u8g2_font_helvB14_tn); - GFX_setCursor(gfx, bx + (day < 10 ? 6 : 2), by + 10); + GFX_setFont(gfx, large ? u8g2_font_helvB18_tn : u8g2_font_helvB14_tn); + GFX_setCursor(gfx, bx + (2 * cr - GFX_getUTF8Widthf(gfx, "%d", day)) / 2, by - (cr - GFX_getFontHeight(gfx))); GFX_printf(gfx, "%d", day); - GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); - LUNAR_SolarToLunar(Lunar, year, month, day); - char festival[10] = {0}; + GFX_setFont(gfx, large ? u8g2_font_wqy12_t_lunar : u8g2_font_wqy9_t_lunar); + GFX_setFontMode(gfx, 1); // transparent if (GetFestival(year, month, day, actualWeek, Lunar, festival)) { if (day != tm->tm_mday) GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); - GFX_setCursor(gfx, strlen(festival) > 6 ? bx - 6 : bx, by + 24); - GFX_printf(gfx, "%s", festival); } else { - if (Lunar->Date == 1) { - GFX_setCursor(gfx, bx - 5, by + 24); - GFX_printf(gfx, "%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month]); - } else { - GFX_setCursor(gfx, bx, by + 24); - GFX_printf(gfx, "%s", Lunar_DateString[Lunar->Date]); - } + if (Lunar->Date == 1) + snprintf(festival, sizeof(festival), "%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month]); + else + snprintf(festival, sizeof(festival), "%s", Lunar_DateString[Lunar->Date]); } + GFX_setCursor(gfx, bx + (2 * cr - GFX_getUTF8Width(gfx, festival)) / 2, gfx->ty + GFX_getFontHeight(gfx) + 3); + GFX_printf(gfx, "%s", festival); + bool work = false; if (year == HOLIDAY_YEAR && GetHoliday(month, day, &work)) { if (day == tm->tm_mday) { - GFX_fillCircle(gfx, bx + 30, by + 1, 8, GFX_WHITE); - GFX_drawCircle(gfx, bx + 30, by + 1, 8, GFX_RED); + uint16_t rx = bx + (large ? 36 : 27); + uint16_t ry = by - 2; + uint8_t cr = large ? 10 : 8; + GFX_fillCircle(gfx, rx, ry, cr, GFX_WHITE); + GFX_drawCircle(gfx, rx, ry, cr, GFX_RED); } + GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); GFX_setTextColor(gfx, work ? GFX_BLACK : GFX_RED, GFX_WHITE); - GFX_setCursor(gfx, bx + 25, by + 6); + GFX_setCursor(gfx, bx + (large ? 31 : 22), by + 3); GFX_printf(gfx, "%s", work ? "班" : "休"); } } @@ -290,9 +304,10 @@ static void DrawMonthDays(Adafruit_GFX *gfx, int16_t x, int16_t y, tm_t *tm, str static void DrawCalendar(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data) { - DrawDateHeader(gfx, 10, 28, tm, Lunar, data); - DrawWeekHeader(gfx, 10, 32, data); - DrawMonthDays(gfx, 10, 50, tm, Lunar, data); + bool large = data->height > 300; + DrawDateHeader(gfx, 10, large ? 38 : 28, tm, Lunar, data); + DrawWeekHeader(gfx, 10, large ? 44 : 32, data); + DrawMonthDays(gfx, 10, large ? 84 : 64, tm, Lunar, data); } /* Routine to Draw Large 7-Segment formated number @@ -337,7 +352,8 @@ static void DrawTime(Adafruit_GFX *gfx, tm_t *tm, int16_t x, int16_t y, uint16_t static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data) { - GFX_setCursor(gfx, 40, 36); + uint8_t padding = data->height > 300 ? 100 : 40; + GFX_setCursor(gfx, padding, 36); GFX_printf_styled(gfx, GFX_RED, GFX_WHITE, u8g2_font_helvB18_tn, "%d", tm->tm_year + YEAR0); GFX_printf_styled(gfx, GFX_BLACK, GFX_WHITE, u8g2_font_wqy12_t_lunar, "年"); GFX_printf_styled(gfx, GFX_RED, GFX_WHITE, u8g2_font_helvB18_tn, "%02d", tm->tm_mon + 1); @@ -345,52 +361,61 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui GFX_printf_styled(gfx, GFX_RED, GFX_WHITE, u8g2_font_helvB18_tn, "%02d", tm->tm_mday); GFX_printf_styled(gfx, GFX_BLACK, GFX_WHITE, u8g2_font_wqy12_t_lunar, "日 "); - GFX_setCursor(gfx, 40, 58); + GFX_setCursor(gfx, padding, 58); GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); GFX_printf(gfx, "星期%s", Lunar_DayString[tm->tm_wday]); GFX_setCursor(gfx, 138, 58); GFX_printf(gfx, "%s%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month], Lunar_DateString[Lunar->Date]); - DrawBattery(gfx, 30 + 330 - 10, 25, 20, data->voltage); + DrawBattery(gfx, data->width - padding, 25, 20, data->voltage); char ssid[5] = {0}; int16_t ssid_len = strlen(data->ssid); + int16_t sw = GFX_getUTF8Width(gfx, "25℃[1234]"); memcpy(ssid, &data->ssid[ssid_len - 4], 4); - GFX_setCursor(gfx, 290, 58); + GFX_setCursor(gfx, data->width - padding - sw - 2, 58); GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); GFX_printf(gfx, "%d℃[%s]", data->temperature, ssid); - GFX_drawFastHLine(gfx, 30, 68, 330, GFX_BLACK); - DrawTime(gfx, tm, 70, 98, 5, 2); - GFX_drawFastHLine(gfx, 30, 232, 330, GFX_BLACK); + GFX_drawFastHLine(gfx, padding - 10, 68, data->width - 2 * (padding - 10), GFX_BLACK); + + uint16_t cS = data->height / 45; + uint16_t nD = 2; + uint16_t time_width = 2 * (nD * (11 * cS + 2) - 2 * cS) + 4 * cS; + uint16_t time_height = 20 * cS + 4; + int16_t time_x = (data->width - time_width) / 2; + int16_t time_y = (68 + (data->height - 68)) / 2 - time_height / 2; + DrawTime(gfx, tm, time_x, time_y, cS, nD); + + GFX_drawFastHLine(gfx, padding - 10, data->height - 68, data->width - 2 * (padding - 10), GFX_BLACK); - GFX_setCursor(gfx, 40, 265); - GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); + GFX_setCursor(gfx, padding, data->height - 68 + 30); + GFX_setFont(gfx, u8g2_font_wqy12_t_lunar); GFX_printf(gfx, "%s%s", Lunar_StemStrig[LUNAR_GetStem(Lunar)], Lunar_BranchStrig[LUNAR_GetBranch(Lunar)]); GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); GFX_printf(gfx, "%s", Lunar_ZodiacString[LUNAR_GetZodiac(Lunar)]); GFX_setTextColor(gfx, GFX_BLACK, GFX_WHITE); GFX_printf(gfx, "年"); - GFX_setCursor(gfx, 40, 285); + GFX_setCursor(gfx, padding, data->height - 68 + 30 + 20); GFX_printf(gfx, " %d周", GetWeekOfYear(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday)); uint8_t day = 0; uint8_t JQday = GetJieQiStr(tm->tm_year + YEAR0, tm->tm_mon + 1, tm->tm_mday, &day); if (day == 0) { - GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, "小暑") - 50, 275); + GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, "小暑") - padding, data->height - 68 + 30); GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); GFX_printf(gfx, "%s", JieQiStr[JQday % 24]); } else { - GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, "离小暑") - 50, 265); + GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, "离小暑") - padding, data->height - 68 + 30); GFX_printf(gfx, "离%"); GFX_setTextColor(gfx, GFX_RED, GFX_WHITE); GFX_printf(gfx, "%s", JieQiStr[JQday % 24]); GFX_setTextColor(gfx, GFX_BLACK, GFX_WHITE); char buf[15] = {0}; snprintf(buf, sizeof(buf), "还有%d天", day); - GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, buf) - 50, 285); + GFX_setCursor(gfx, data->width - GFX_getUTF8Width(gfx, buf) - padding, data->height - 68 + 30 + 20); GFX_printf(gfx, buf); } } @@ -405,13 +430,14 @@ void DrawGUI(gui_data_t *data, buffer_callback draw, display_mode_t mode) transformTime(data->timestamp, &tm); Adafruit_GFX gfx; + int16_t ph = (__HEAP_SIZE - 512) / (data->width / 8); if (data->color == 2) - GFX_begin_3c(&gfx, data->width, data->height, PAGE_HEIGHT); + GFX_begin_3c(&gfx, data->width, data->height, ph); else if (data->color == 3) - GFX_begin_4c(&gfx, data->width, data->height, PAGE_HEIGHT); + GFX_begin_4c(&gfx, data->width, data->height, ph); else - GFX_begin(&gfx, data->width, data->height, PAGE_HEIGHT); + GFX_begin(&gfx, data->width, data->height, ph); GFX_firstPage(&gfx); do { diff --git a/GUI/GUI.h b/GUI/GUI.h index 833c6c4..ec7aa5b 100644 --- a/GUI/GUI.h +++ b/GUI/GUI.h @@ -3,10 +3,6 @@ #include "Adafruit_GFX.h" -#ifndef PAGE_HEIGHT -#define PAGE_HEIGHT ((__HEAP_SIZE / 50) - 8) -#endif - typedef enum { MODE_PICTURE = 0, MODE_CALENDAR = 1, diff --git a/GUI/fonts.c b/GUI/fonts.c index 493b404..7f27f5f 100644 --- a/GUI/fonts.c +++ b/GUI/fonts.c @@ -150,19 +150,163 @@ const uint8_t u8g2_font_wqy9_t_lunar[4430] U8G2_FONT_SECTION("u8g2_font_wqy9_t_l /* Fontname: -wenquanyi-wenquanyi bitmap song-medium-r-normal--16-160-75-75-P-80-iso10646-1 Copyright: (null) - Glyphs: 13/41295 + Glyphs: 142/41295 BBX Build Mode: 0 */ -const uint8_t u8g2_font_wqy12_t_lunar[271] U8G2_FONT_SECTION("u8g2_font_wqy12_t_lunar") = - "\15\0\4\2\4\5\3\2\6\17\20\0\376\13\375\14\374\0\0\0\0\0\241\60\16\267**\233\212\224_" - "%\62\231\11\0\61\12\265.*\221Q\177\62\20\62\16\267**\233\212T,\325g\203A\0\63\21\267" - "*\32\203H(\27Keve\242\310 \2\64\23\270jZ\61U\42\24\311t\22\212\14\6\252\134\11" - "\0\65\20\267*\12\7\262\262\201\256,&\212\14\42\0\66\22\267**\203H*V\61\321$RV\211" - "Lf\2\67\16\267*\12\7\261T\254*V\25\253\1\70\23\267**\233\212\224*\221\311l*R\252" - "D&\63\1\71\22\267**\233\212\224U\42#Y\304\252\42\203\10\0\0\0\0\4\377\377^t\35\17" - "\11<\361\370\340@\223\12\246r\261\344\340 \25J\206\222\241\330\340\303xg\0e\345\21\371\16\14\17" - "r\336\15\16t\276\33\34\350\2g\10#\14\15<\203\233\134&\227\311er\231\301M.\223\313\344\62" - "\203\233\134&\27\11F\202\211\134B\231\0\0"; +const uint8_t u8g2_font_wqy12_t_lunar[4891] U8G2_FONT_SECTION("u8g2_font_wqy12_t_lunar") = + "\216\0\4\2\5\5\3\4\6\20\20\0\376\13\375\14\374\0\0\0\0\0\246\60\16g\25Q\331T\244\374" + "*\221\311L\0\61\13e\35Q\211\214\372\223\201\0\62\16g\25Q\331T\244b\251>\33\14\2\63\22" + "g\25\321\30DB\271X*\263+\23E\6\21\0\64\23h\25\323\212\251\22\241H\246\223Pd\60P" + "\345J\0\65\20g\25Q\70\220\225\15te\61Qd\20\1\66\23g\25Q\31DR\261\212\211&\221" + "\262Jd\62\23\0\67\17g\25Q\70\210\245bU\261\252X\15\0\70\24g\25Q\331T\244T\211L" + "fS\221R%\62\231\11\0\71\22g\25Q\331T\244\254\22\31\311\42V\25\31D\0\0\0\0\4\377" + "\377!\3\26\255\65\341\220F\62\213\222\32\211$U\334\353XQp\20\1N\0\10/\320a\370\1N" + "\1\17\355\325`\370 \26\356\177\232\310\346\0N\3\24\356\361`K\367f\220\32\210\6\212tg\275\33" + "\14\2N\7\35\317\321`\370U\274|\60\10\246\202\251\134,\27\253\213\345R\301P,\21\12\246\0N" + "\11\21\217\21\341\30<\310s\63\70\320\363d\360\1N\21!\317\361`\31\34$C\311P\62\224\14%" + "C\251\301A\60\25L\5S\301T\60\25Le\6\37N\31%\357\321`\370]\274p\360 \222*I" + "\225\204\22\241H(\222\211dB\221V\221\332H\66\222LD\242\21\0N-\31\13\332\340\212\266\32<" + "\12\211B\242\220($\12\15\36\204\252\242\255\0NY\23\315\365`x\240\355\217\263\321D\64\21\215\14" + "\16\4N] \17\322\340\212\67\35\34$C\311P\62\24L\5S\301T.\226)\313Dr\231Dr" + " \7N\214\15O\61a\31\34\350\371\223\301\7N\224\34\317\361\340\30<\310\305\233\16\16\202\251`*" + "\230\12\246r\261\134,\27\313\14>N\245\37\15\326\340J\347A\203\7\251lU\253\301 \223\313\304\64" + ")QH\225\10jR\262\304\62N\262\42\17\322`\313\3\222\203\3=,\225\314\244\6\337\305\203\203\7" + "\301l\244.S\25\252\251H\345\202\0N\272\31\17\322\340\213\367:\21Nd\63\321L\62\25L\345\252" + "\222\231l\42\35O\21)\17\322`\252\14%C\301T\60\61\70\210\250r\242U\42\64\212d\22e\231" + "DY\244U\42S$\252I\5S\301T\12Q\77$\17\322`\252\14%C\311P\62\224\14%C\311" + "P\62\224\14%C\301T(\223\12Eb\241Dp\60\7QC \357\321`\31\34\350\231\14\276\312D" + "\63\321L\64\223\14%C\65\251P$\26J\4\7s\0QT$\17\322`\212\307\7\203\134\254\331\340" + "I\42\324\37\15\16D\231D&\27I\4\63\221X(\322*\265\33\14QZ$\17\322\340\213f\352\42" + "\231\134\244j\360@\21\26\207\6g\271X.\66\70\314D\63\311P\211*\64\34\10Qk \356\325`" + "Lf\222\231d&\231If\222\241\134*\227\312\305R\271T\60\223\314D\23\341\0Qm\34\357\361`" + "\313\3\362\200x\36\66\370\236*\23\15\5c\271\252`(\32\311&\0Q\233\36\357\321\340\30\70H\0\206N(\16\322\340" + "K\17\206\301\301\223P*\22J\250\22\3MQMj\240Ig\6\252LU\246(\23\212$\42\251\210" + "$\67\206\307\60\357\361\340\211\345\312r\241\201b\60Pt\226\250\220E\22%\271DI&\63\220\24%" + "B\211\134H\230\210\244\62\203Dj\220I\244\22\271\301\0\206\360,\16\322\340\11\5C\251\201b\260\12" + "ER\22Id\20\212$\62\25=II*R\231\301U\246*S\65\270\14E\6\17\42\321\0\210c" + "%\17\322`\313\3\342\271\301g\361t\42\234\10\305\62\221\230&\21K\204b\221T(\23\313%R\61" + "\235(\12\213\336\60\17\322`\316$\67\211Ab\25\312$C\301L\42\263\30$\22\233P\242*\21I" + "T%\42\211\252H\242U\242d\240\221(#\245\241\301&\13\214\67$\17\322`J\5c\65\241V\221" + "P\42\233I\246b:\211V\63\70\313\305r\261\134,\27\33\234\345\62\0\217\233\32\17\322`\313\3\222" + "\203\3=,\225\314\244\6\337\305\13\7\17\202\361\356\0\217\260%\357\321`\31\274\211W\14\216\342\361\301" + "\233Ha\244&\24\311$R\221P*\223\12e\22\241HH\246J\2\217\330&\317\361`\311\14\6\242" + "X.\226\216\247\6!E,\223\210\244\42\65\241D\246(\25L\5S\271D\66\63\70\10\221I(\357" + "\321`\370U&\232\211\15\36D\62M\62M\212\62\221Dl\20\221F\262\221\301\203H\66\222\215\14\36" + "D\262\11\0\221\315\37\357\361\340\315\16D\203yn\360]tp\226)\33\234e\312\6\247\311\301\201\62" + "\67\370\0\225\360$\15\326\340HG\6\3IRk\61\270P\245T)\311`\20Q\245T)UJ\61" + "\270\320*\23\322\4\0\226\63*\355\325`\30\10\63\211\301@R%\251RdR\222*I\225&\61\30" + "h\22)M\42\265\210\244\24\231\224*\245\32\14T\5\226M\60\16\326\340\213\15$\261Ld\260\210\24" + "E*J\62\211\224(\22\61\211l\42\233PMb\60HdB!EM(\21\31\34\4C\301P\60" + "\4\226d\62\356\325`\30\204R\221P*\21J\204\22\231\32M*\222\250\30(&\241T$\224\212$" + "\6\3\205\42\224Jd\22\65\241H\233\26\251D&\21\213\1\226\350&\357\321`\370]\274p\360 \222" + "*I\225\264\310D\62\211H\253\222\26\231H&\21iU\222\312$\42\321\10\0\226\352#\17\322`\31" + "\34(\203\203\7\212TL\262H,\202\321Eb\217\32\34\310\253\6\7\361\242\301\201<\2\227\34\60\17" + "\322`\31\34(\203\203\7\212TL\262H,\202\321Eb\217\313\14&\203E(\244\31l\22\222P\244" + "\42\61Xd\212R\231\301*\23J\0\227\62/\17\322`\31\34(\203\203\7\212TL\262H,\202\321" + "Eb\34\33H\6\232\212\222\314@$\313L\26\211i\42\64\320$&\231\310j \1\227R\42\17\322" + "\340\213\7\7\17\202\311\301\201\62\67\370\36\63\70\313\305\6g\271\330\340,\27K%bE\0\232l\27" + "\356\321\340\30\34\244\313\372lp\240\256\36