From 668ba870e4e84991770a14305317ae0bfafbd777 Mon Sep 17 00:00:00 2001 From: Vlad Adrian Date: Sun, 28 Mar 2021 17:08:14 +0300 Subject: [PATCH] Added draw 3d text example (#1689) --- examples/Makefile | 3 +- .../resources/shaders/glsl330/alphaDiscard.fs | 19 + examples/text/text_draw_3d.c | 751 ++++++++++++++++++ examples/text/text_draw_3d.png | Bin 0 -> 58003 bytes 4 files changed, 772 insertions(+), 1 deletion(-) create mode 100644 examples/text/resources/shaders/glsl330/alphaDiscard.fs create mode 100644 examples/text/text_draw_3d.c create mode 100644 examples/text/text_draw_3d.png diff --git a/examples/Makefile b/examples/Makefile index c8fc3fb26..270f736ca 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -450,7 +450,8 @@ TEXT = \ text/text_input_box \ text/text_writing_anim \ text/text_rectangle_bounds \ - text/text_unicode + text/text_unicode \ + text/text_draw_3d MODELS = \ models/models_animation \ diff --git a/examples/text/resources/shaders/glsl330/alphaDiscard.fs b/examples/text/resources/shaders/glsl330/alphaDiscard.fs new file mode 100644 index 000000000..d2134a688 --- /dev/null +++ b/examples/text/resources/shaders/glsl330/alphaDiscard.fs @@ -0,0 +1,19 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + vec4 texelColor = texture(texture0, fragTexCoord); + if (texelColor.a == 0.0) discard; + finalColor = texelColor * fragColor * colDiffuse; +} diff --git a/examples/text/text_draw_3d.c b/examples/text/text_draw_3d.c new file mode 100644 index 000000000..3cf5bb6d8 --- /dev/null +++ b/examples/text/text_draw_3d.c @@ -0,0 +1,751 @@ +/******************************************************************************************* +* +* raylib [text] example - Draw 2D text in 3D +* +* Draw a 2D text in 3D space, each letter is drawn in a quad (or 2 quads if backface is set) +* where the texture coodinates of each quad map to the texture coordinates of the glyphs +* inside the font texture. +* A more efficient approach, i believe, would be to render the text in a render texture and +* map that texture to a plane and render that, or maybe a shader but my method allows more +* flexibility...for example to change position of each letter individually to make somethink +* like a wavy text effect. +* +* Special thanks to: +* @Nighten for the DrawTextStyle() code https://github.com/NightenDushi/Raylib_DrawTextStyle +* Chris Camacho (codifies - http://bedroomcoders.co.uk/) for the alpha discard shader +* +* This example has been created using raylib 3.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (C) 2021 Vlad Adrian (@Demizdor - https://github.com/Demizdor) +* Copyright (C) 2021 Ramon Santamaria (@raysan5) +********************************************************************************************/ + +#include // for NULL +#include // for sinf() +#include "raylib.h" +#include "rlgl.h" + +// To make it work with the older RLGL module just comment the line below +#define RAYLIB_NEW_RLGL + +//-------------------------------------------------------------------------------------- +// Globals +//-------------------------------------------------------------------------------------- +#define LETTER_BOUNDRY_SIZE 0.25f +#define TEXT_MAX_LAYERS 32 + +bool SHOW_LETTER_BOUNDRY = false; +#define LETTER_BOUDRY_COLOR VIOLET +bool SHOW_TEXT_BOUNDRY = false; +//-------------------------------------------------------------------------------------- + + + +//-------------------------------------------------------------------------------------- +// Module Functions Declaration +//-------------------------------------------------------------------------------------- +// Draw a codepoint in 3D space +void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint); +// Draw a 2D text in 3D space +void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint); +// Measure a text in 3D. For some reason `MeasureTextEx()` just doesn't seem to work so i had to use this instead. +Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing); +// Configuration structure for waving the text +typedef struct { + Vector3 waveRange; + Vector3 waveSpeed; + Vector3 waveOffset; +} WaveTextConfig; +// Draw a 2D text in 3D space and wave the parts that start with `~~` and end with `~~`. +// This is a modified version of the original code by @Nighten found here https://github.com/NightenDushi/Raylib_DrawTextStyle +void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, WaveTextConfig* config, float time, Color tint); +// Measure a text in 3D ignoring the `~~` chars. +Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing); +// Generates a nice color with a random hue +Color GenerateRandomColor(float s, float v); +//-------------------------------------------------------------------------------------- + + + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT|FLAG_VSYNC_HINT); + InitWindow(screenWidth, screenHeight, "raylib [text] example - draw 2D text in 3D"); + + bool spin = true; // Spin the camera? + bool multicolor = false; // Multicolor mode + + // Define the camera to look into our 3d world + Camera3D camera = { 0 }; + camera.position = (Vector3){ -10.0f, 15.0f, -10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera mode type + + SetCameraMode(camera, CAMERA_ORBITAL); + + Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; + Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + + // Use the default font + Font font = GetFontDefault(); + float fontSize = 8.0f; + float fontSpacing = 0.5f; + float lineSpacing = -1.0f; + + // Set the text + char text[64] = "Hello ~~World~~ in 3D!"; + Vector3 tbox = {0}; + int layers = 1; + int quads = 0; + float layerDistance = 0.01f; + + WaveTextConfig wcfg; + wcfg.waveSpeed.x = wcfg.waveSpeed.y = 3.0f; wcfg.waveSpeed.z = 0.5f; + wcfg.waveOffset.x = wcfg.waveOffset.y = wcfg.waveOffset.z = 0.35f; + wcfg.waveRange.x = wcfg.waveRange.y = wcfg.waveRange.z = 0.45f; + + float time = 0.0f; + + // Setup a light and dark color + Color light = MAROON; + Color dark = RED; + + // Load the alpha discard shader + Shader alphaDiscard = LoadShader(NULL, "resources/shaders/glsl330/alphaDiscard.fs"); + + // Array filled with multiple random colors (when multicolor mode is set) + Color multi[TEXT_MAX_LAYERS] = {0}; + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Handle font files dropped + if (IsFileDropped()) + { + int count = 0; + char **droppedFiles = GetDroppedFiles(&count); + + // NOTE: We only support first ttf file dropped + if (IsFileExtension(droppedFiles[0], ".ttf")) + { + UnloadFont(font); + font = LoadFontEx(droppedFiles[0], fontSize, 0, 0); + } + else if(IsFileExtension(droppedFiles[0], ".fnt")) + { + UnloadFont(font); + font = LoadFont(droppedFiles[0]); + fontSize = font.baseSize; + } + ClearDroppedFiles(); + } + + // Handle Events + if(IsKeyPressed(KEY_F1)) SHOW_LETTER_BOUNDRY = !SHOW_LETTER_BOUNDRY; + if(IsKeyPressed(KEY_F2)) SHOW_TEXT_BOUNDRY = !SHOW_TEXT_BOUNDRY; + if(IsKeyPressed(KEY_F3)) + { + // Handle camera change + spin = !spin; + // we need to reset the camera when changing modes + camera = (Camera3D){ 0 }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + camera.projection = CAMERA_PERSPECTIVE; // Camera mode type + + if(spin) + { + camera.position = (Vector3){ -10.0f, 15.0f, -10.0f }; // Camera position + SetCameraMode(camera, CAMERA_ORBITAL); + } + else + { + camera.position = (Vector3){ 10.0f, 10.0f, -10.0f }; // Camera position + SetCameraMode(camera, CAMERA_FREE); + } + } + + // Handle clicking the cube + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + Ray ray = GetMouseRay(GetMousePosition(), camera); + + // Check collision between ray and box + bool collision = CheckCollisionRayBox(ray, + (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, + (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); + if(collision) + { + // generate new random colors + light = GenerateRandomColor(0.5f, 0.78f); + dark = GenerateRandomColor(0.4f, 0.58f); + } + } + + // Handle text layers changes + if(IsKeyPressed(KEY_HOME)){ if(layers > 1) --layers; } + else if(IsKeyPressed(KEY_END)) { if(layers < TEXT_MAX_LAYERS) ++layers; } + + // Handle text changes + if(IsKeyPressed(KEY_LEFT)) fontSize -= 0.5f; + else if(IsKeyPressed(KEY_RIGHT)) fontSize += 0.5f; + else if(IsKeyPressed(KEY_UP)) fontSpacing -= 0.1f; + else if(IsKeyPressed(KEY_DOWN)) fontSpacing += 0.1f; + else if(IsKeyPressed(KEY_PAGE_UP)) lineSpacing -= 0.1f; + else if(IsKeyPressed(KEY_PAGE_DOWN)) lineSpacing += 0.1f; + else if(IsKeyDown(KEY_INSERT)) layerDistance -= 0.001f; + else if(IsKeyDown(KEY_DELETE)) layerDistance += 0.001f; + else if(IsKeyPressed(KEY_TAB)) + { + // enable /disable multicolor mode + multicolor = !multicolor; + + if(multicolor) + { + // Fill color array with random colors + for(int i=0; i 0) text[len-1] = '\0'; + } + else if(IsKeyPressed(KEY_ENTER)) + { + // handle newline + int len = TextLength(text); + if(len < sizeof(text)-1) { + text[len] = '\n'; + text[len+1] ='\0'; + } + } + else + { + // append only printable chars + int len = TextLength(text); + if(len < sizeof(text)-1) { + text[len] = ch; + text[len+1] ='\0'; + } + } + + // Measure 3D text so we can center it + tbox = MeasureTextWave3D(font, text, fontSize, fontSpacing, lineSpacing); + + UpdateCamera(&camera); // Update camera + quads = 0; // Reset quad counter + time += GetFrameTime(); // Update timer needed by `DrawTextWave3D()` + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + DrawCubeV(cubePosition, cubeSize, dark); + DrawCubeWires(cubePosition, 2.1f, 2.1f, 2.1f, light); + + DrawGrid(10, 2.0f); + + // Use a shader to handle the depth buffer issue with transparent textures + // NOTE: more info at https://bedroomcoders.co.uk/raylib-billboards-advanced-use/ + BeginShaderMode(alphaDiscard); + + // Draw the 3D text above the red cube + rlPushMatrix(); + rlRotatef(90.0f, 1.0f, 0.0f, 0.0f); + rlRotatef(90.0f, 0.0f, 0.0f, -1.0f); + for(int i=0; i", fontSize); + quads += TextLength(opt); + Vector3 m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + Vector3 pos = { -m.x/2.0f, 0.01f, 2.0f}; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); + pos.z += 0.5f + m.z; + + opt = (char*)TextFormat("< SPACING: %2.1f >", fontSpacing); + quads += TextLength(opt); + m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); + pos.z += 0.5f + m.z; + + opt = (char*)TextFormat("< LINE: %2.1f >", lineSpacing); + quads += TextLength(opt); + m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, BLUE); + pos.z += 1.0f + m.z; + + opt = (char*)TextFormat("< LBOX: %3s >", slb ?"ON":"OFF"); + quads += TextLength(opt); + m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, RED); + pos.z += 0.5f + m.z; + + opt = (char*)TextFormat("< TBOX: %3s >", SHOW_TEXT_BOUNDRY ?"ON":"OFF"); + quads += TextLength(opt); + m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, RED); + pos.z += 0.5f + m.z; + + opt = (char*)TextFormat("< LAYER DISTANCE: %.3f >", layerDistance); + quads += TextLength(opt); + m = MeasureText3D(GetFontDefault(), opt, 8.0f, 1.0f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 8.0f, 1.0f, 0.0f, false, DARKPURPLE); + rlPopMatrix(); + //------------------------------------------------------------------------- + + // Draw 3D info text (use default font) + //------------------------------------------------------------------------- + opt = "All the text displayed here is in 3D"; + quads += 36; + m = MeasureText3D(GetFontDefault(), opt, 10.0f, 0.5f, 0.0f); + pos = (Vector3){-m.x/2.0f, 0.01f, 2.0f}; + DrawText3D(GetFontDefault(), opt, pos, 10.0f, 0.5f, 0.0f, false, DARKBLUE); + pos.z += 1.5f + m.z; + + opt = "press [Left]/[Right] to change the font size"; + quads += 44; + m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); + pos.z += 0.5f + m.z; + + opt = "press [Up]/[Down] to change the font spacing"; + quads += 44; + m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); + pos.z += 0.5f + m.z; + + opt = "press [PgUp]/[PgDown] to change the line spacing"; + quads += 48; + m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); + pos.z += 0.5f + m.z; + + opt = "press [F1] to toggle the letter boundry"; + quads += 39; + m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); + pos.z += 0.5f + m.z; + + opt = "press [F2] to toggle the text boundry"; + quads += 37; + m = MeasureText3D(GetFontDefault(), opt, 6.0f, 0.5f, 0.0f); + pos.x = -m.x/2.0f; + DrawText3D(GetFontDefault(), opt, pos, 6.0f, 0.5f, 0.0f, false, DARKBLUE); + //------------------------------------------------------------------------- + + SHOW_LETTER_BOUNDRY = slb; + EndShaderMode(); + + EndMode3D(); + + // Draw 2D info text & stats + //------------------------------------------------------------------------- + DrawText("Drag & drop a font file to change the font!\nType something, see what happens!\n\n" + "Press [F3] to toggle the camera", 10, 35, 10, BLACK); + + quads += TextLength(text)*2*layers; + char* tmp = (char*)TextFormat("%2i layer(s) | %s camera | %4i quads (%4i verts)", layers, spin ? "ORBITAL" : "FREE", quads, quads*4); + int width = MeasureText(tmp, 10); + DrawText(tmp, screenWidth - 20 - width, 10, 10, DARKGREEN); + + tmp = "[Home]/[End] to add/remove 3D text layers"; + width = MeasureText(tmp, 10); + DrawText(tmp, screenWidth - 20 - width, 25, 10, DARKGRAY); + + tmp = "[Insert]/[Delete] to increase/decrease distance between layers"; + width = MeasureText(tmp, 10); + DrawText(tmp, screenWidth - 20 - width, 40, 10, DARKGRAY); + + tmp = "click the [CUBE] for a random color"; + width = MeasureText(tmp, 10); + DrawText(tmp, screenWidth - 20 - width, 55, 10, DARKGRAY); + + tmp = "[Tab] to toggle multicolor mode"; + width = MeasureText(tmp, 10); + DrawText(tmp, screenWidth - 20 - width, 70, 10, DARKGRAY); + //------------------------------------------------------------------------- + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadFont(font); + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + + + +//-------------------------------------------------------------------------------------- +// Module Functions Definitions +//-------------------------------------------------------------------------------------- + +// Draw codepoint at specified position in 3D space +void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint) +{ + // Character index position in sprite font + // NOTE: In case a codepoint is not available in the font, index returned points to '?' + int index = GetGlyphIndex(font, codepoint); + float scale = fontSize/(float)font.baseSize; + + // Character destination rectangle on screen + // NOTE: We consider charsPadding on drawing + position.x += (float)(font.chars[index].offsetX - font.charsPadding)/(float)font.baseSize*scale; + position.z += (float)(font.chars[index].offsetY - font.charsPadding)/(float)font.baseSize*scale; + + // Character source rectangle from font texture atlas + // NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects + Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding, + font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding }; + + float width = (float)(font.recs[index].width + 2.0f*font.charsPadding)/(float)font.baseSize*scale; + float height = (float)(font.recs[index].height + 2.0f*font.charsPadding)/(float)font.baseSize*scale; + + if(font.texture.id > 0) + { + const float x = 0.0f; + const float y = 0.0f; + const float z = 0.0f; + + // normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f) + const float tx = srcRec.x/font.texture.width; + const float ty = srcRec.y/font.texture.height; + const float tw = (srcRec.x+srcRec.width)/font.texture.width; + const float th = (srcRec.y+srcRec.height)/font.texture.height; + + if(SHOW_LETTER_BOUNDRY) + DrawCubeWiresV((Vector3){ position.x+width/2, position.y, position.z+height/2}, (Vector3){width, LETTER_BOUNDRY_SIZE, height}, LETTER_BOUDRY_COLOR); + +#if defined(RAYLIB_NEW_RLGL) + rlCheckRenderBatchLimit(4+4*backface); + rlSetTexture(font.texture.id); +#else + if (rlCheckBufferLimit(4+4*backface)) rlglDraw(); + rlEnableTexture(font.texture.id); +#endif + rlPushMatrix(); + rlTranslatef(position.x, position.y, position.z); + + rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); + + // Front Face + rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up + rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Left Of The Texture and Quad + rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad + rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad + rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Right Of The Texture and Quad + + if(backface) + { + // Back Face + rlNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down + rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Right Of The Texture and Quad + rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Left Of The Texture and Quad + rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad + rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad + } + rlEnd(); + rlPopMatrix(); + +#if defined(RAYLIB_NEW_RLGL) + rlSetTexture(0); +#else + rlDisableTexture(); +#endif + + } +} + + +void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0.0f; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scale = fontSize/(float)font.baseSize; + + + for (int i = 0; i < length;) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetNextCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + + if (codepoint == '\n') + { + // NOTE: Fixed line spacing of 1.5 line-height + // TODO: Support custom line spacing defined by user + textOffsetY += scale + lineSpacing/(float)font.baseSize*scale; + textOffsetX = 0.0f; + } + else + { + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint); + } + + if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; + else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale; + } + + i += codepointByteCount; // Move text bytes counter to next codepoint + } +} + +Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing) +{ + int len = TextLength(text); + int tempLen = 0; // Used to count longer text line num chars + int lenCounter = 0; + + + float tempTextWidth = 0.0f; // Used to count longer text line width + + float scale = fontSize/(float)font.baseSize; + float textHeight = scale; + float textWidth = 0.0f; + + int letter = 0; // Current character + int index = 0; // Index position in sprite font + + for (int i = 0; i < len; i++) + { + lenCounter++; + + int next = 0; + letter = GetNextCodepoint(&text[i], &next); + index = GetGlyphIndex(font, letter); + + // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1 + if (letter == 0x3f) next = 1; + i += next - 1; + + if (letter != '\n') + { + if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale; + else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale; + } + else + { + if (tempTextWidth < textWidth) tempTextWidth = textWidth; + lenCounter = 0; + textWidth = 0.0f; + textHeight += scale + lineSpacing/(float)font.baseSize*scale; + } + + if (tempLen < lenCounter) tempLen = lenCounter; + } + + if (tempTextWidth < textWidth) tempTextWidth = textWidth; + + Vector3 vec = { 0 }; + vec.x = tempTextWidth + (float)((tempLen - 1)*fontSpacing/(float)font.baseSize*scale); // Adds chars spacing to measure + vec.y = 0.25f; + vec.z = textHeight; + + return vec; +} + + +void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, WaveTextConfig* config, float time, Color tint) +{ + int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop + + float textOffsetY = 0.0f; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scale = fontSize/(float)font.baseSize; + + bool wave = false; + + for (int i = 0, k = 0; i < length; ++k) + { + // Get next codepoint from byte string and glyph index in font + int codepointByteCount = 0; + int codepoint = GetNextCodepoint(&text[i], &codepointByteCount); + int index = GetGlyphIndex(font, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointByteCount = 1; + + if (codepoint == '\n') + { + // NOTE: Fixed line spacing of 1.5 line-height + // TODO: Support custom line spacing defined by user + textOffsetY += scale + lineSpacing/(float)font.baseSize*scale; + textOffsetX = 0.0f; + k = 0; + } + else if (codepoint == '~') + { + if (GetNextCodepoint(&text[i+1], &codepointByteCount) == '~') + { + codepointByteCount += 1; + wave = !wave; + } + } + else + { + if ((codepoint != ' ') && (codepoint != '\t')) + { + Vector3 pos = position; + if (wave) // Apply the wave effect + { + pos.x += sinf(time*config->waveSpeed.x-k*config->waveOffset.x)*config->waveRange.x; + pos.y += sinf(time*config->waveSpeed.y-k*config->waveOffset.y)*config->waveRange.y; + pos.z += sinf(time*config->waveSpeed.z-k*config->waveOffset.z)*config->waveRange.z; + } + + DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint); + } + + if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; + else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale; + } + + i += codepointByteCount; // Move text bytes counter to next codepoint + } +} + +Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fontSpacing, float lineSpacing) +{ + int len = TextLength(text); + int tempLen = 0; // Used to count longer text line num chars + int lenCounter = 0; + + + float tempTextWidth = 0.0f; // Used to count longer text line width + + float scale = fontSize/(float)font.baseSize; + float textHeight = scale; + float textWidth = 0.0f; + + int letter = 0; // Current character + int index = 0; // Index position in sprite font + + for (int i = 0; i < len; i++) + { + lenCounter++; + + int next = 0; + letter = GetNextCodepoint(&text[i], &next); + index = GetGlyphIndex(font, letter); + + // NOTE: normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol so to not skip any we set next = 1 + if (letter == 0x3f) next = 1; + i += next - 1; + + if (letter != '\n') + { + if(letter == '~' && GetNextCodepoint(&text[i+1], &next) == '~') + { + i++; + } + else + { + if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale; + else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale; + } + } + else + { + if (tempTextWidth < textWidth) tempTextWidth = textWidth; + lenCounter = 0; + textWidth = 0.0f; + textHeight += scale + lineSpacing/(float)font.baseSize*scale; + } + + if (tempLen < lenCounter) tempLen = lenCounter; + } + + if (tempTextWidth < textWidth) tempTextWidth = textWidth; + + Vector3 vec = { 0 }; + vec.x = tempTextWidth + (float)((tempLen - 1)*fontSpacing/(float)font.baseSize*scale); // Adds chars spacing to measure + vec.y = 0.25f; + vec.z = textHeight; + + return vec; +} + +Color GenerateRandomColor(float s, float v) +{ + const float Phi = 0.618033988749895; // golden ratio conjugate + float h = GetRandomValue(0, 360); + h = fmodf((h + h*Phi), 360.0f); + return ColorFromHSV(h, s, v); +} diff --git a/examples/text/text_draw_3d.png b/examples/text/text_draw_3d.png new file mode 100644 index 0000000000000000000000000000000000000000..ce92959808c3277d3dace4e329283c14de9eba25 GIT binary patch literal 58003 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%11H+>zPZ!6Kin!!IzrMb% zZwoY#Vp^<-gDBx(Ty`-)j<@lmfCN^8v8wez278Lh+TOMU85})W2!oz72RGq^*d=?~ z4s76VyeK*0qKhpqXE;DL1MmZ%N2o3_ENoDcpEQ%aBtB!d|A0-xqH;FiK!-=`%r_8=e$6JslIY&My zc<{}(&~<8x*q!iB@oMf4sbdPCS17ihmkFp4Oy=KvsLEhTN={;*cF%{-%cu39EHQub z!{uE1k3W6u*q@c>JlgWfTC+~o++OH$*&=I&JKAeIxVqOrJbvJnN2vdaf~2#}Go4pi zuUOijD1s7m3Y?5iyw4ws1is*{dD5m}S@fdUIZ3MX#~Vq{nN2r7920kU*4%U9^UZJ_ z*?$+E1Wj4o(jDA_kDx^H2LXljD`K`MJS0yZOO-#IVPh~sXx)`rnG#wb9Z#2VaeY51 z!}r2i+`w*SCd1A7CyZroT$0t@tb9^d;KmuIjeUof&buPXJEL~VE&nxkG4B+w+o2^? zXBCzck~`h!3pQNe?$Y<~Qt=dtXl34KaV3^scUsTOExPR+aj5@757V||8k!%SyJt$r zBs#9KSXXi2seaBwZ;d+}mNI57@s7#tx?-THepcbOqmRU-S@|nNm-L=%=n3mb$q|Q~ z8|JhbFYV3EGW)~nD*wqtziKg0wDQzDZW{a8^i@53u6=aQj1kKE^EgXHSlRBvL$|D` z15?>NMAeVpztUk}^~`<3eK%``#aG{<1W_9Uv!?Rt1rHXbESV9;Tk3R?W0Sa9w851{ zbFO`KUiH&i^^eEL>kdo3lMV@4zFoBZ;d+sGmXaLx{bder+H+Ad!$QS|I};9?c6qI_ z(Ck%+>e(TjtyZPpGU5M!xhPR` z#VKLSLCaZb?8O{C%g!&HZ8y_x^EK4aMal0Mv{^tgkeO@3;^v%yg=olAG`Phm>6?RM z4RV=O!p%78d&7iX*PG+2oma>vIbXfIxH27!Q3)n2Y{eWs=NfvJoks~U-bP1xri&LZ z@+kP|w@*rvUwg+b-@ZSs`J%vra1Mc5{u3EfQ1T(zKMt)7D-8FQybRj#^+e8$>J6QN zufm+t4n4Vex9x1)jN6@s!ixKw&MauHzj(LpG+)x;)D6$Ya%7_dY#s_7eO=y{kx=EPe8$*V_`STa1#r zh3=>!*5=DG!D^N7sSICO93){K3K4O}0 zdE#I5O@F^RL6aCedf9UxHp`VCDJfbZD!1eqzbSX;MZOamOO26(d9k9w6DNlF#S(i1 zxjxI}RPz2Zl8$-RnVIr9s9C2k$Ifp1!7l>09~{3Hp?XaJ#jgo(m9N*n=*@m&a9qr7 zOONt|+9Ss_HzxM#Hw#GfE0ms?s}l3FDIo2Lc>RtqLc;5JT+(6YJ&?iPf>z{ZaPVvu zP*^V5cDnzFnNy+Zri*8fUQ>|udFb8iX1=MugIB!7b_)ja66B4!=-yc5+%V&qsAcb)gEA|2xE=8Ec`76a6@p)r<;n zx_4Qq_GXk+pWu~$;>WRRf2W~*{EW$u>{7Pwc*J;j?u(k7v<1hNiz+4y`70Ek_{zVQ ztLDMYY^d=oHR*C&7~^?Uz}$r4OUg!5E|Ha7nG?%fyJN{&S1WPqaPq zFxdO2;q1JN6N`VP{&_ed%)R?0MjBt>&JplbL?=gi`+{ToD<9pk;mLLpmXbZD>aV^1 zp^^A}`Gle;E!;l*`}|l9WnF^q^yaB=topd}@U?*DVKRY_%meOBc(kpt=lR7&g&6t0 zt%xJwtwdZ7Z*mTAQbdB{>BMY{rYnl&NfWG!pE=73o$*UsN~RHg8^a!UqgyX&9?lgVE8 zmMdNgIRk+GZXTCZ5BGb*nnQO7H#SzsB~&yMI<5ei4hp ztQNN3?=YP#_VG{Y7nU^_gKAA!GQ^lph_^LLUEHDfZP7O76Si8yk@9BSgdx7Vu|=B9VuvRr~6g%wFHy%Ui(IU(;@s@x{&#H$Ca{PD>FCTi+Avn z;G4cf;pq9piuc^SV{f%HT$B~4>5YpiI@0wxYf0i||CO;D6jYDfpSb9F@`TC8x`vg? z*Y$FKb((fh+2HQK?8+zkU6wlzF;A;o@zUJuu$+k66^{1xi;Wc)e?5@Falw{lLvPt3 zE6o>uitaKgY-jkAq_UrwB^CZ;zRCaN%7Wb!B|dL(72Emjz#re&KNd{;`J&Ff-#q7= z!gAJ>zgK+nw|tRb_v6^}x}2BuuNC&_#~yleqR_bL-_o+Gqv0POa<6YJ5?;w_>ifOn zK@rc&#fNwnCz!BIa7r-w+oRSFj@zhqhALIQ&HUl*jY404{Bg>A&OE!i(6qs`&{}Wn zk3S8%XFN>XqaJpjl_~kI*e<;CBQH05%tyB#dylR1mTz7@wNJV%ZupShsQZS+0=GK? zMb;}bd81>3h0gEzq`9twt#k6K_DLpgYd4iUSSd7DhD^Vew|IKI`z4Q`3142n@Hv{% zTw%iE=Ekug{L6+mHbY*9Am@%t=h!#$3J2Zs z&8S#lQvYC9>cLb!&3{U!?@oL?jb8pg5oj9Y@NRXs=6-Yd`#P{gPje z5?>b|f7Bqr|zq_|+;m5EO-E)H`y#?kBw5Mv6lX64=+%=9=}T9)1PNnz*W z>h_SoPj0YZZoYHS!JPeBT1}q%HUATJOQ!wb&?>#FKA|S2&e@zf)^;DCgl5_$E5DPS z?H8L;Fp69^=LS1Phv~@`g{E&ln*Nx$w}17+?(;D@vIH*lGpow>5zQ$U7w)4?rTkqqryu#|jW&-eH^}PS&U%$8&BT0*QL!{d zRzzfq$&}8G{r5QgZbUMrlwUk0-;!2)f>Szcrf1ju!q%4wJ^wE<P*m7R2D16Vnu=}0Eryp;Ql?uxF$ZxyBcJkq5`995*1@B%+=#)1HY-M(O)nRM6 z_{t9}nJZGF?q=KHUCAEJZyz)tBT=XJ3Li^9lE;)8E z~=j#g*7Ay;eT{|HU`Hr3Nx*BX2l2tl{I>c1(Vy z^3Nk?DTOPQRrn^mFTdE_D6wC_hLhhFkW*{J9f1Sa9FAX;IBt5Ye{EuK{t>A(`Av2?y`@QaTzlrTZ+h6jKA5@Kdga5e zcj++?`+a5C8K}C-r0A`DwqSRw(BCPyd_6rKuLf^$tD4xF{X{mLxoS&?JSdYOwHV?Q z9lVt1PKa_kox0)W@vD*tuX`>m<9RT9*)-6`j|0$0_mJl_e*#hup3(FD$iAzX|x-aQ*k?{Vt7Gnp2AH2pR4 zt8mtW$(z4$-q)}x4dosg~{f6+aGaDXQfR9C8mj(iRrKj%LQxZ6TOjN+RO|c8`c&(uCZM5 z;%KUxVcEn-ayQlpt~}jeP`b$>vBSGhX#3;M{Fe6|UTyf+Gtl#+W`YU#;E=@{%s4C%eEz$Tzt&O z7}fp|)S38-QpAF@odF+X%;K9*dWw>x54nQese1LS!q*LM#=GKzq%Z$?b1aR0*Uueq z)UU>5sd*M1624iNRqi3NzwYm^`Yl%^F@p4>fP|DHL$=SQq$#terA?OJbz&}eig7__ z|FXvip=r4U(`Nx37m6y+Bt-0Ud6n@u40J+;3--{cWEdOaeUn|e{T_vq~(ffp6(V1h*+Nb5ooITGh&9va$@m^_ji6u*yKICgG^>AR? z;K$j)`+CNLa<78U{$p>!A%;u@XtQ`kHMQPLIDYlV^71baUa|0oeeYAde^FpT8HY{n zuPKZzrY0s56Rbr~%oR+rzL@TnP^4h&kQ3m}rq-4%mReGlY9iZ@I$SwHm?`8Yb5r)R z#;8YM`l9l-sK)(B3%YREZB1OzVYZucUU!&{*kkQiEOuKnb4y>g*P+xUVvIYi{}TX57_& z45dsCvMgU_@@I*apOED&N(*;*$E^Fm>FkW2bL)D-+)(o7Cg+Alsu4$6WY-)WfYwU^qNn3}Rr4WE!6?l6~s zg0-Wu_TtUji?5~= z+0U8p>TmGGRR6>A-wd^mm8 z`308y=dYO2a(8x8TAG&iep2M+f9(i7!EJU z?GUnZ&DvlwM@ss!^bCGB|h+2}ooa%PV~6+xFXIgRAzN6umD`eHFIu znAQ;Muam-1+Vf(g3C~Vu##b7GvzAKQ9;?{$Lkdx#bwS22w=Y&SIN`*w&81`7_SwOw zPd7jHNJvWabI4ozgvBs`y)|yGz=Y_`jZgTlCGN}J;!qW(< zDypP;8y!WMly`n+ymh#7&z_E17o9xaJFj19Xq59lobXTeO5mdFL8eJ*;SPDMJEgBQ z9^C5Ax{U31kimqwld@iN0RgWqCK{UICVuAT6V>$cPZ{J{W9sq#YKp+xZwt*nK1RDfCP&o z!|b07maNC*)*Ro!_bpN?Mt0Ig*|H>>;(GR%6_wDkzgntWgVfaeS;W78wMW?#BF)qA?0AqNLXgW-vD7bhQd>;4O~0P4g87X>5^2pqWf;>fid zhfKBl)^27p5)N19R_V(!oUFYbPI=y3X;@iQ^K@Kb|~M{_^Lj0T&`^ zZD<3}%q8};9bjl>cvDvF)wf=C+h(TMD;oB6-MMh+`U$7^DGgVe(!w)#x^zs6>^Q$% zpJA_fztHR-RxD3)D%7{ww?r6Uyvv$>fj{JU-xVE)^EdguHa}nN-Y=1onp!C3{PGRg ziG&C{rj73D;cly^K)tOX1I~USMp8`70!$muvG2Y1J6T$kty22_$JH-nMQ>bM7rfl> zpmWc(?FEyoq<;nYo>*{9Ta&k{YW}HKxpmEz-6}JC_t~`2Z?DK+}%yq5*FP?e`l=DHOJywuugd7u=7a~j>c<(H5I~id4vLhh9^VRQA zBV|bmzj&789B1+(z6eNhvY9TMIQ>vUcUX-qQ_bw_r7{G**}@d|Kx*e>VNSQ_BX6_7SEk}F)I(;?$`jC+w|>gV~}-XsAT?L@Umut zRL+sIu!Q4Jn+|o}_^V~GUEoy%&$1(aul}kSY`^?FPUwk&bk=5hh3$*=_cxWYEN%S0 zdqQyrqwZw^&4=FS-kf^j_WR;1sPQe}M55c*#?b4WpiyS$z`L+<-b%)s{n;TBVyO!@ zOtstA_;6P!Lj=c_%%3T%&VS(C#nN3E$8J-$v6rd&h(nd*vw&TUb1oFAe^HHhUTbK7 zB`w=Q(0;<{^=!cht#)0k+cFD0cp;Gk&TYPv7b`j(7HBB7YdiGz*@lFMvr0UzGo`-x zF`qblNpvTV`t&vI)$C>4xjLF(pGewwHCWQ2&MhvPKk6UrC1&IQmzSRp@l|bJ*zCTl zz3tIG{+!e66HY&xcj04MbwETssFc(dK2pAe$<*r56t$2iHm+wF7<6L6)%#L#`L+b& z-@QF;482YaA%@K#0$$fNNI6cC;q_VjK*eM+!)Eqtkq6TBxB0&KAr-peY5aVr&5|aK z#@ZX)MCC87;o25_AffEAResC2)eTn^%lp`()sAcpf5v%X;id3zyfclM@4pOZ-ukEO z!aNF91+!jm1*&XFRz^xJ~-VNGX_lxMJd$ld1*tS4@w_aa3Dp0n&Klv^f$P4M8g z8B8k~O9MLIu6e-inPi=L#plrvsSD4VR}>q`Op8BwNJ?bgi|KJm-N8YJ=1=0bIO*%Z zi}D<_GgmZ*S2O0_!Ds$4 z|0K>y%3psOexkP`B6)7yT#K_m|4KOeWtg>Gu{e}E@29}5txn%QzqmK`;;Tv%mbQFw z5CnhE;0Q2enIL`CSv4VXvuSgsr$ALilU2orr@1>0&Aj0zzT%?W+KUNE(oKjvU5U~^U1x?mN?mk&zs9DpUsY2=OKcwVYIfbwm3%=* zFK`PTFI8YPJ=`+uW&gC(>tEO|X4$16Y@5ST+O)!UbCY(SLvMN36UVA)whG^yPW4~B zIrZYIdJ`5lGjI{3SzyAlLV#(*#nT5jRL+ige<00HBU08AU`Z||({pB2bI z#`&!N-=BF0cO~)9xZD2BDCjwrsOj86T?(R04rQqh=@C%ZiLl-MLBytGs(ycLIGx#K==H+Hk9x}6e z?{V4Pa~Y4d{S;SWORA53ygivk zbKzgD6H*tfwG?(PG;`uBGF~Ui7FF((kl32Tuj}{P$*!qlL+mk+ejDCdR~J8>c>Kwk zbq}Jr+Vt$IR{zbIoVo)NdAj{=46KRR)1FMU?olt@_0WssZMbFUQG*C~78TbQ5ur}*Vv}dtdPdf{zTfRo@RRk5 zgqz*k&ahUawcjWAgsClQXV9E0dc%S3gjmqGbqn~J0<6#X9{ZiaF+mty>y;QwF{QLH z9gx`=72^FPkUz-u{sm=y%CN@bI)~-Xns0 z7K`#eRcx5^@1nKnk9V<(%QiC=-F@-qREE~lbZ}0(d^>|>CO1}%1wg%OPnrzS4k)i_V2eDY=y z9+CMcWW@sFTAm)i=&j^F+xrR+xQ?!p;$;+aVz|%4v~uz8B|UF~lqbE|7}FCrw|}A8 zWtMD~%eU{|uoByFm~jV@37M*rg2X!IRC~@(L59Uz_g)&t^gWQ(oGOuXp<8V8 zyAzr6GkZ_#1+jCsB}v-dvRIT04x`{385{zVpf<|7;Kdty%>=D={W4O-pScvJhrGD@ zb3s`WQ!BT|o%TyFlQtME_XE^jdluiBmocQ=J+^T!B*Y^rnag_MG z1$!)~Ok1EdeKE74wP$8c!zHVAe5QM~i-OX_9Uk(o+TV6d=UWDIXBi~3#V%HKaN#&G zEh_MFS#ec)$cno^9rBMH>c7t_ceuMwNKCbpTkM&0?q$mp=b5kW*vKl^$a84Np}7}? zv?FF*-W6aV|6uk`M_K-W!#{;5xnH#2xx=j@@#F6|S2Q=|d0ju-{HAecqujeK_e|`n zSl(Y){m&t@HEwh16)xF`x$Ii;pyd<3dJ*7oyL>2vLx6)ZtIW=WGbgJo#38#Xkyq;r zSHqM@(I={524-9PZo9s_(O_jd-@Z1D;bK~vvvw!nku|(JZyaPD1a{~Cm0i==Ruj(c z!MN>r)Pduy$uAXnz6Dlh#oKl0{$h>s_!1tAl ze@a=~tAC;qH!W^)CQ7g#0QUmanlB0*5N6uIG+D}6ehXJdjI8L54B?zkmThf99y~1* z&1E0Gn$Y6A@7#wPttU<9U-rsfxv_`Gm^r1aUO}E&em)QLnYUM7J-MK~vH8&4d*-K= z+wC_NHr@$re95>|_Il4{hx1Vnx~+@+_b)oOtR&|r|C6w!>G6mDuyR#@d1^X;iHqcc z)C(`W3*JAL@=%zv&AtDDYm0!!IkwY5YC)$}qTVqtEd9yB_5EU`KwBUKFE~R4N$@ht zC>jVT-@MYrlaseR#m#l?BcbL-6K&=dm*OfuNgw_flgM`AlHP>s{L&YV(w+v}gNr_i zuL$HZ;!hE)V(y!!ZW3sG$MKyUmvYUEhn!x<&V{!28w=a_?3_F2$FdYQj%DJN#kOa7 zH`I!p$Yk3V?z-8gz46X(xdPqSQo0}7%Q$%2&t1-tlHp|xfJEuR42}fO#)sE_DyUAn zXsxy3X8U4UJsyK^S7O)=q)n8aRy4YtlBx`N&U{57x?DEI?Wj{r$+#Bv~w%TE3IKM!JFCdQPp}NPX9p6?pOi_658c?Go%{|MPkzZ=cQo|D; zJ~l2*$T}fwBGKjDn2=~B@;!*BbbIrqPXT=2FCG&rg)~MMxj8fFvYdEXb3p2u!s3p| zbpO>3%gc^)R=yOrlD?+tAph1~-c`M<*Jec$lWB&7Nd`Z2#xYhAzuT+NNVFYVc6y;r zv%!?Re(O)Ov!50+`Qpd3Y4?QBN*eM?t6AShFD%*5rC}drbl5WLW`H`2!$+GC>-q&H zoLc#A-y3_LwShXpQWCt3O9UF`O1Qq-xPHMgi%)I|PaItD>pNyPJbv}2L2HS^S$m!< zHl|$HPBPpTX58)0RB}gKv(90DVB<^I_bVFulv+C*)0`Ym?{mmXT)bt2>FpG922cW*m)f?8O;LBX6Z?|nMk~atm|oLVNgAO_0cUA-__^Xe@#-E@i(;b zT1dBF%J##4p-dMSNXljDcOJUeu>VNIS-GIJkc3|OfOfVmopqt>)R?Q1J1|Fq{x1ttQob~ITDU9oEAN$V>KvuWlLc&ug6 z@p8?9clrmXsV6eCD}27l&Y$p8DDAt$nN>VbBU={k;b#&1zId|&kFp$ipyNOW2ZM9N zrQJpo(zz0Ti+zaYaQ9sB_*G5Ax8#6q7tWo5edm@vii!&6YKAbSN`eD^&ToM z(-~asUoQT6-Py{sAb8E2#y*>!8SH+``JP?gogjUolQTW(Z{zyKPOFtGHa_*NS>Dk2 zr#p8)m!Y_0(CW=bQ_=+;9-3eIzCocpz+GBV*%;C$t9NN<$oV1_(ipU>hHYn{M|UJs zfQzEJnWJ~Xwz*Xtc5}J5_&3d(%ReFZ#b&E5v(9D~C8iY2`7`?=(}#ClH-gNv&TLRH z@7kv~t!?>d)&s$N66PM^_OCzO|4TL9*mlk2<~?^>=1F$VILBVK%dt#;t+oFKx6cmu z6pd!Q*I#(ls;)*>RFY}4+!nvxCsIX>W=~P>p2#kc@b2hUP05a#qE%1p1Ag#cjbxc{ zyS<1#Ys*cKx!}Ta*%Co%rUl28Gmh|v{0vNfYq!RbBWp!)@ic~L7RB;1htu6FuKql5 zJ!0vzP1+NFJI+4yyZJ}M-2Ux62GtY)x^}m8uAkf?*Y+Zl>9&#Zjb)Vq&J7n{=x&vA zUh?kXLGk=AQC4O%(iPoSGkkJlm?EEX^P^hXGT|pxMP}Cz*YKWVb}rn{wT96?)k&mSt#S>Yxf_oYAd$)C<_0mdg<5&u{=vRCcrS{ESo>hz4ZPew* zf?4=t2N$E4wfu?2Urub6-7@1R!_3aLhMco37hF5To*~b<&CUK-kZOR^!D|ndOg|nt z!y5WdEtg*+V`mO;xcfw@xh@gx( zbAGqtz#luAGV^;03HZ^>~P3bRvd>%Z}%Cc7$EKg};+8NCJs^)-@obI>U2d`v;7BA+= z-gCM5i&S(vYq;}^LzmefEI4{CkWqFv7kBxWufLmX59@tO`($rCTaqPipYrNAhswX` z*m56UXuxb5Wh*4k^n_1MVK!fOhw$#{JWI+~yk}-?y&W+BsN`AYC+*-djITW%0u8z| z70XX@ZtMP$z?+_>zx&Yjie*RV@uz%mev{Wc&yCef;zZq&C7&5z?P<_6Dw$e&zG2Tx zdCQoUQw1hko9wvpf)Ar1%0cXU3>Y&UieM<=U~TXXP3!#VITjE zjXO@vmCaIhxzYRf#IwNFn=Jyor%$jBx^alpw(rAH$xkP&Exo-xWLGXtS;kS8qw_0p zSHHZy+Dc}l8-0(Ke&r1MqH!g&u*G1nwsOENnKStuaz!)Gl{!7up^jlD z^DCRi8xzj8t26t|nU=`$`aodvd#)3EL1TRWvdm|N9&)KqkU5ciMDDD27JJu}rSS^o z7qZ+~e@@Z9aQ69w-~T?w*je1*-um!Dh5TA8c6W{gX#xpPFD2Yv-=x2#?N{8ii+dd6 zz==Ni+y-983nv8L%wzj9dtGOwo73r9mKTkE=k+f5-koArmB<@%!AL7$v1sKpwrxCI zC6@9YvKiZ$p4erT@Hsqd?Bj8>d&`w#w$;k~#KR67?}j@In>K3BT+7sZj`zx}+6y{@ z+h(6htaG$`&VORhER=3)&wAK6`S^ zWZNDtBkpL43%@)HXUMymFYZ56bNa{E*Vq3qcDRlwBY;Fho?6mxwD?> zlKqv>EQd7|G{GzOh0ko@X8dwY$#C)J6RqkQTjaK+aD*H@@zV^i1P*A$ z1sn)WcGfFeEWd60kzGmr7I7MDB^)6&p(@oteZvt)9Ke`0op$H5a?4 z&r&py@SCJmDkk!z{z)Ha2fucvd`p?%43e&=8}0>^2$dB-PN01Z=L9qyLlpSftyo9Y!-)+ z_Q5&aPmgFvshXtNADE`qm@#3$Ca-hEQVW5_-7hu=D{L3gZj-yVpu|dM+ROvf;v4_C zzwu#P$NOT*lh_HhS6;a^pVEwY-kvDJlflvOs6^ww8Xvb!z&$yw-ts3kEoaz%GMZFy zoRYtCDtqzG>;g!M)XLW_(4hO3Q8ej^*_MvGpBv*c7O^XATbU8?v?1oArC;4?hF2*K z@3I(fawp}lH%k7HW6iqHh408RlcWRY-PyC6dmBr6E_`=Pur}<9sZRXu<4~rcf8HVA zMEQN>f-fS5HQwtJsv|Wxj~~2HAfLHee#ay3D?b_L)~Twiy9Z5q^lF8`?q_pv$xeM} z^qVo-$T+ICuZ>}=6GO=MzH?1IbH14DVo%xfM&gsAL+?5Ebq)-st2B51XPUk9hTBF* z?|likoWli-s+(KEI;tXQvnP+udw=*;iAj$To-7~|QQXYcm#?Kx5= zb<*?6f-Zq6+t^P3Du}r8=vBnSS#KTR@$fx8!xvS@T4bNW{LA5Y^OdjfUMTNs){LDf zJ?(I!JokzBhmXoPC(3gy{V5bSo&Q?(GzmAxP-pN!tD* zB-88?dPTjYEEn`~osh{g`PBKlV;zcjdCEMvue4 z1u1C-8$<+RV`F&)1qFGQoNM4&^1JYC+oE_T&$S2Hs(zJjVK&;a>fFU261iu1w+cwa zHkr;!YtP|ma4U1HSYa;Y*gHkxtUb?8y;(drt{oTJ{Dk{5p(6sX8~_k^n`8v!r8cR3qMPI2akAt&$8-6kUCb?*@#8sWlcgf6YIVY{>~gS zVq13Hm5En4?AN8VePYMjgZm#mF=xB*uWy&_dkF>avU`W-GVB%+*k;0h?ZCn%h0I*R zGj=-f-N@}7eK=8)VGXmaWmY|#=F`L=lZB;I)u z>_^#ie!dQnXOPN`d&CdUe_WD9iVWIwPR#wOP-Y@`Es!z)**YV2?KuUdWe#nPc`w+` z)&vw+@@(5HyTdAcfge{YeSR!Mc@GiCED7p31W zG098t-ghD2f_?5Y)OaI-F&wd9y*;^C#r zrXkbgc~f?J_4jd|s6V`LqxGC9hQm)Qo?o1O(cNu#Nr~{UjQ`0eS{Sxk$)AvGGyOF| zdexPCJ9@L9$Xy9|-(kKe>PPZt?lT2hzd2L%&e&bB6aEq@GvUtXmDhMqR0m&3kMM~7 z)GF7fVE!Q5ian}|E&GJ9@CoKxChnp?iJ!H1$xpD>RIq%)rofBe2RxoIOP2Y<8_pMx94}}Fyl~%oDNER5Tdn+wI;VL~?)f~EH$UM{lV9=KDWhuM zlymGFPHaWT81^1+)ZRDYYNOfh<{uk&u*L4PO`IKg@LGnt zs(Yegaf%uQYz)%&;w_bCz<*jWq5ILvIG| zm>IPvc+0YGw7=o6%A1!D8V|j{k3UIBRP(fpgL>7$Lwr|GG@cDR@Mhtc5`}CvFV&|jXipw zrS~m830gkIY_!6ep>jTpB_FHll#QlmHol#>;HnN|(R1dI8BJC}S6;n2aEIrUx<-wI zu|mSHU)EC|IL&Kacx1jox%!M^Lz~)P^A;-KoAc}?d&tVBwDN?x%tij}hpu}vn%-i6 zbw&HjP5u~0uQgT^;{WB}IsAd8bWp& zhl0N1;;`q;PwYzUFDdIeik7N=c;s@y_xS=o{%x~&IzHqsk~THFs(f5}UoC&jpT68m z4iBEce4<~T#yV#n5uI{wo=^0N0}O9!GS0nkW!$)(Oyoz)Q)(Gc> z61EhRM4nv&4Z7#m#Hs+n58DG6=ka~KBt0d~|tp`Q&8hae3 z^MX&ZzefL{F$`r4bSZr+GpmUIQ{#Awd#g8WnH}%=XWs++bvb+ z>Q0DUz}MEY(~h}&BO~*x9CsVHFLj45X;yN*I>8VcXCKQF=KtQ0E9a-^VFSj)sV%hz zZtP2qwHEksE&Rj#>HCXM`oE6tdc?NpkJid2M=R}l51+4TuK{fKsu@2Qp14A(t!<>g*YbQIMzB%P# z$uCh2oA%2d?+T<--Sw|)%nX#|krfSyQvN<~&B1FbQhAxVTTXUzfVaM0G01RgxO9#^ zM^m&)nYTns?lMJ}Ii5RKoa7d>(KKm7da%QBgTr_Dg!yOJ$m+06vcC0@ zDedv=2@8J9Zu!o9A6=95ncvo!X_NiL z_uh@MZ#bf!u|@BW+wo5LMrQG&rIHi06P_I7K4bsCakKoh@Nb5H7|zu-q&Z}~R1a`( zmCU`yqT-gJ#`;99>ijaE5=HYnZiViDouj%AnMp97W1p{3DLw7_%Bz8rz4C2=1}skC zhJ_Ei4U5LxnuN~`pH>FkF!OvIZRVQUa3HN{g(WNByj;iKD`lr!XI?Zsur;JJOjd5j z{S7nug%+1gYrnHJ{K_ev9e-Gj7Z3C7Jj@*B*7m-SC#!^G z!%@k7ZdR(Y6B_e)l;TA?_5BjPUpXW?zq!YMHd*>WwLP2j^X3~h9cw3VdUma}t>Xj- zTTyzjgY*l>k{7w|SZs;jn!M5$L!+Xi82QPR@?Uk$rbp)g2c^Ox=GOQ3{7G2_; zJB6+CCr{B~`4U6<7b>D&e(w*7?${tHo8(u!Xp1vLwnDSi-VJSRIhg`yYOlQeaNx|* zauuUZyHEJGY~Xw3aQCO z*)g^rPte%ZetB6!Kn34+K8_RqhjUwG%X(}xBE^3NKAxYk{L+hb?pbR!p>GOL~7iLC?r>uE@776>Xb8x;~hEfGwCkWkXrj$1bQkRdHR*U~hS+$dGN)_|2n%%dW_8o5Gehxo4VL@4hNr z`MKlj!s8C-I=!B_FjPGjePR~l&Nw;C?#%q(#jOYbIlhlsSYEN>;sm$t%xP*qbEN8| zd3x1S>K}UfFZiLfba7M7r>h?N=Ny(-?`^ynZxnHeDdZUM^5D+4Y$@rJ-+dqKQs&%i zclc^xZ+59=iI0wKKlr*X+csb<8*9Z(Li^q$TzwGdiG| zWv8>#xghUr;q3o#YH*w3()mO1cT*vFqGE6?*uzUn!%tzSp(n#sb`Z&+Cw z6lYW>Dxcts`o*2{FF^XLikXdDy8VXbU!?6NBpkliH%v?PWY$kPQp(R!CCOmK8{0Ew z>&qRVWOEqOEMhs>KfNxP!zkIS-KNOgmK|f*V_ zHfyvP zK=FgNKa;Kec%EJ8{rO~BY|K-J6E-&(*cSSoDu}see2Y;sD!1)nRms~IXJ0t)e`|G% zQSxnlfGtbHT>cA&ySG^VWxd~8x}_`V$zGNhy}~)YqDj-M8t-uL&JZZ!lznlnxWxWK zQM2tf-{)KA&2;!Kult5MG+@gPkx5g&wC>x(bw5XV)6O4Onu|Bf-$-WI@}IeczvIuH zI<~A5hmOwlBr8pY;tjg*7hRpCUlo$MxcAn=%LNj1Z%XDq;k_mxahKU>mf1=vrVWAV zQDt@xe9NvMZQgLeQQp_x{%P}!&zCM@!Nb5=Ghk5)}VlQv_{dV*#-q2=s!uQ2#yF_MFgYQAfC&l;vvD>viHN#Y9!sUAj1wZet zbeEX3Iaj0T)QhnKem~ruDEn(06m&j1Ms$=WyfWs^) zd@C50X4Z=2sN{$-sfc}%+;abkEpx__-352m*>3C;o?yK#d}ia-V5`k6pS9Oqc0Pam zNnxwvRx8B~g8L8FJZIl$aA5ke19NX&thV34Cb)umk;#cHlP7IfMe~kcGdyNCyD9rZ z(+p=5w`{XZ&J0&LS&lNVO?$_#miDrN6O9D*0yW@;yceveieAK?)*dT;8%J_g4_mx?a z2h!xK4yWusroLnE>LOFg6&Dp6OYIWW;}mauu9f6?;?jC&qw<#jj3V3Qa@94xCNFTi z?{NQTDJevU_-sd9!Pt&DgM4e!=Cr4&^aD_kK5WTr{8H{7S+h@$=~b`5MWE z&;I;l)V<4Yq`OFdR%3R*lt#menZAA_s&q?I}R35s3EApk#llFs~zI4rU<^J@BeZ^3!&@j#BVv>q%*(1?i_b=%GUp(#p#OY;sUL_NoCC&^|a468f@){G~*5S^ImW4d3fWF-Ta1#q$NCq5mT_w6E-8H5$k3@Q zZ|n7T!O?X66M7eX7<9E1o}6PpA@`+^U)Ne*;deo<6}#yl&fIV6Wm`nl@E5K3ush zp+qbtW7_}4N6ijvD5$c$xcGCy7Q?Rd_8azc+(?s8;7zV70o4Jkon6jO;mls3{F`^L zv&+ib1#KLkCg~jctHi^z;M~>ED<=r=y)eD1@!Qe{EB6JevOC;7Kk9xx^lbaXNvqw{ z?KzIC{Ng#W{Ia+tXe!Z!^MKX$#ap?RSTtfkvChtw_4>Y)XW0+-R{KvqUkkiuAHJD? zcqfk}D8&f4v@&FT;R>l}l-e-G2jmIE#+6EMwnRC{sH{L+x+?a8`ieK1`ftAkINm+7aGsmW1-Q+5x>0B zgl{7#1#2o?KKXJ5&-b=B4)2&9?YhK8?7Nl~J#bl&q2~Q@Y0HKmY**PA|IB+aMGw@N zoYj!P5pd~e!&!?1W{S$@UKh<{n`NBNrh1$(=H9?&{wXcv$uY~d(_;@xExqwAI>4Iq zkX4kz{-!^ySx1!S^RRN2N9|(Xc2aKR!MTl%5&svPJ8-;pWh}Kzc)g9YcfzIBNlyEY z%7|=V@U-PcArCiyjXUq*H2Zl>=JRLA-#pG>_4C#Fo8605K|6|H2rMW$DZWnm)I{de zEsEZ|Rodz|wSk{9@~uA5lzBz}3K zwCxQm`5RW|3Z+|K)im7cd&4&)e!}6VTfglbWbJZh@66n}pXJI!hkKiuKg%z4W_8F@ zeZG!A!lFs)g@V~aKQ0g6oMkM_#4E*ERoZg5Ou4be-K%EOBC#zhzOQ&vu5pxodH3RF z_==51kJ*`-KYiSN$N0BIoI|=p$^!K^UKc_8Iq%gNo~l0aec`;5>*!W}))2V^R$7NM zPhNL8Ci^S3<;XJWpm%JN>%Q;cxt{jw1rNtzjRT@g3%uA`PVT%bb4|eQUCo163=MCV zFH!7zSNFtCuBZ3(JL6C;o-H>%GZqP-$@_9nT-TcU#KVp~Yj|$w2p8=LG*WI_`?>L* zd(KA(&pC&+f^y310+J8gSoZQ|9n%Kw20zE1QrNRi z)=!oLufPmx7GzrBBplK?$@nv4^nZRMk-ddocMK1h8#{U?OQf-Hy1QYi!-nV`iT@Ud zK4*SX7jT??+ke(tPZ8a82ZyrDhwBxp6aG2(W!G$ux$?<;jk3e)nc7d-m=^k-YF*BM z;G}3tK99!v1JiU4T{8F-q<=&3NXw<~FW#^hsxo9S?~;*T6(yE@;bk~;wddo4S&9h~ zjSN$spX_x0;>a6tVWRbh#u&E78(-cnxuA7x?xwW|-OhK$^DTQnzpmx7Rz!O9m6?+l z-a07NS(ytS3z*>CFzJ}~ii`YNZDK-kWjrCDYQt9Pjln=1x}K+<$28k+MzV8nuVN z%~LqtoOUl^yGL?%!~yGw#hc|>7MB>@YdB}%!dQM`^JYt&fgC^=mi&@+tz5IE?s}(-Q22{#u-Fc|6?DNN(Ri@1AQjNBF@ot&%(XmW>ox$>} zYV|Q?mv7lsovE8JnT_M^#)D~UYnquRHJh3p*sS4w&Dem!e_zs^>x|cy%?mY*@>tk< zK-wdECgWcwr+>!3CDy5nHBC?W$a^7H!8uo1XU*e}TiFcdIE9>_DYO4iINN;Xl*$H2 znW%FUf)B6VaF91;^M#`YZ@n3HxusV)%0$T@=jQ6ac=mQ8b&$9BcUn6HA}e$}iZ^(8`~&tto7-LX2_b4J+3vXR0n{XG$7o z3O_S{!Y7{7DR1`oMxUA+pM1oQ15)J*#t!NUjqm<4m~L}a{=0bbU+2XeXYM<=rTUM8CFd(*5RbK+## z0xsbv_EGQtDqM@bVI{KTi;%T8%j=q&RWBRwKjF3h$+hL7R7+ynf^v_9xsxYe@^rMX z6BpB4AUOflEm}|=%(f^)UTg95BW=9f{7!jD#LAsJuF?ER&XRBA+)u5(J$F>&ubgRL zB6HIE&f^J*5)Bt61==R^YP_sDkoUt){-s;~k4w80d-Cj89Av*$&e(M`M!b;i2JgEq zQDv;JLLO#MxU}nX>)TC^6Ygi`>Kn@HXFb&mcwDog#4cg>dq-orAALe@@zYvg3;8^` z$sh5&>wL(3#w{%`9^1T;UUku0WrM2c20yNCd?yQLx;pOvD>Lobf$a|v>QmzDoXs5=onK7RzaYmy!Rp660VU_j7c?VI9P7z*lmFuhS`g91 z9pq&tzaXJG*Xa1RhcYVtcNi9jCQDr7JakQf#dLz;_JIAYRxgE^x87;Iw{p={!|gvN zsaGBEZcMahw*6Lf;10{{ipI1#4oO>XRq(y4;hEO^{6u2kYG=nYn{*;>9K6I^#Qxg8 z;Qb*`Bjdx{M1?Ce8%kX!r29JXe!mzg(iUhS#iVS8<*SnWyiZ8I~H-uW<=^60(Y zd+NipW9)1fcwZ<?Df1gQ32lqb-}uwufFs;^pyA0BQ$xNh>) zsi_ktPj22Va)iBb!qI|C=4%ShCSL+WmCm~bSZg?x9hR!TVdZ$^n@hlH-XHJ88E-bO zUCbUr~41IPCqhpdteq<$`P zOR-lt&cF4q$C*hwMd^VKbrL6*#x3X*`SkXAvu13=scQ!}xD;%8v{Z-1?a&KL-9H|0 zG~-WlD@j`EE^AiS%-O`xyshu_#lFuE__)^jaT%639r(t3>Gy@17yr1&aDb+`HcVkU z^5N6%rCZ8iB zRl1EiNhu>!Xsr};i`4fUey&WW7ZQ6*y(YaMKsA zoB2EbwCMEd>TEb_z3*x2f>hV~b8$;NHC@+6icENX!P;ias|5<@AMhMoRQ-i-!o_9R z1GpL+J=VXN%NX-?_c113wkL}_66a1)JvjS-BhRhJjjyNZPhh&ysI%Zx=@w=qi{Pgj z>?tf$r*AmNUe(54>NX+Wdd=FkfljQ^?5e4=83N9Rva!BfpRkpGUs1FBw`AWN2mfT4 zGm98!Y-Hh1Q!8qg*jZ>dL3!erh)Jwn{yFZhm$G(BYdCejtO+<>ccbmz!Gh=P>yntl zm$%F~$92YMf<1dOtLGaXt`qVb`WS!3iA<2Ga&MO?E^IYFAtz|F^_uzv-4_e~8uKtS zIDF*D7BJ*VZm7Hcz2J+MhCSc+b1FHVmmJRDc)07K%=bz99_%b3`U0DubSH}N+!6pC z$2s8$=j)mY#k(!5*pKEOQ!iN2C^c(C+qHE(b_;IEvu&4rf1t=;|4mc7&NfMrq-o_3 zyQC(}ZQl9W@wE!;te+Xt<+Bs-mWs64f1M!vBvIla zs3XNB#E>JbZ#kF$%Y%bvw;R?PA2{%U^Lke<8|$_`+)Fy9@NsQB$G%BAbLShbE$z(r zWBI>$c`f*n({H}$c52s&LcjHAzuk~})~vYtQB;y^kA>cM{^!SJEH`T`C^)n=QSJ)k z#N@+sh4NzdAN=tDa{7mhj}$^rBzC`*2&`JB`Q?~>hyPkWM$Ut8v!XJ08h{o>gd&F0Vh${gA%S6Ug&<-g*f zn%*h?>7Vd~%ng#l7ks!^I5R&wELFSUub3$JdBY2vJ~L*wD968Of8$*>*Ut65@sERZ z^?VgS=x~41VL0*rN19E-aiPh#6D4()$2I=xe3Sph;6Qkdz%0S0r)LlDInpC{R9RE{ z*~hoK51&3xzHs46LdCBCD$F?|B9%J@H1;_DzMoL%^nOA>)laEyyf5Us{~O8F{gBU5 z{guPs(|_+nxUD&wyhLz@yY59t? z*`!(|?)KPOOn#Zco+2T>V1ti)?@ayxgM-uVA9&};&>5JV$+eGwb~5Z_ zzJ9d-N!vk(UYn*zg3<0mv+XDFOCBhd(Kjq~$>@~aypfT4t=U5UrHlBleN@=ODO*xw zsQ*DC`NkRceM==5@G)1hvx=x~@Z(y@yY9uq_O*)Jm8Z>2FlbJbVyjYP30LR1A}N_8 ztI`(euvI`p=eGk#CC8n>lWO;GFW#)sY<#(=%%Lqak?nO&!tEtK>!v3zzWGCH=@mY| z8)w+p`F=XyFP|>JQ08!NZ}S^l#?lA}iR(OEn(jP@|1|A+!+p2@#*-Cye>Rx**fUR` zRx$IWaR@tapNn_*(}*n|+mEz}tx@i+Y0=xZc~D?+^mI;v_Eoq-@hRIoy4hsDo>3LPZXNZ79#=j$a&urf@24?$&b<4j6>1VZY6{V+q+4gzj+{dqhfj8VIr9n!os|Wg2LyU|ZxWhR_xT{lMa9$qSk|u2)qDFrRmrHC55$Ge7gf zub*ESYb+@V5W5%5R4rR_#Gr%Gswg7NPpsyP!HUIBuX%48{C|I5G|eGzO_S7V1IwuL zh8L3GH=H}3VEL2l=KGdIl9p?QUV+BWFQ|n!zVk`6sGPX&sOXx>Owp%Wb>B|feWm+W zyRbsJNz}q>D~I3K9y28+HQjleg)VwzZfLr6)8QR6W2u}&wWWhNU()G4C$=wYev&9F z8Zct!O!y8x@2&NRJ&+UwT<$9L)^AZ=P zPjXZJ=f9AyU2u7O+ilJm`!rn^b|v>)4|Y6HH+b8Bpmde!zCKP3gHB6c?j?C8Vkw{y zM#gWpRvM1IrcMHl_-<>c2D716#6W-(S zY;rOCsYk~4l0~scBprG~zo@2dNG{Br+3vy1>~+`Z#H#ySb{tbKLBwj_(eY zX-Vw$=UV*j(vp5PKb}A7-wgk>lsPzOC(j)Kown2x z%$T!Td4;2MZ)*4tD~T^JY7R)%Em&&zV){SD-=bzo9^EULOY0ntpK5yJzAsTGO?;*D z-zOyjF81|l8P+`n0q_No>4 zS{<{}S)-R1ZBbg}$FYH-Uneag!sGjcBU|;Ew&ZYbE8#Tj>VIRA75Bycj1Jcd#(aez zGY>kv;JzVg$rdlsansV49o@_q^UsrN|M>d)`v30Q2NsGmU3pi-b4ulPI{!XDwyNVT_r4mQS>M&}Z^(1ylEH<{hz+%JKmPRRT8gds%y`N9Oq@X0 zQSHMT3oJm3ZQBx*no8|fY!%^*cAh`4Hy|dkq2`vbZoZ|wk0-;G8IJLO%Oh(=-?%(s z%aaUfnc*$vDAoCP!GTMRYm(U?1y`?UFN)ybc8>i-?hdQ18)o0t+*vYl&Q1OkEB_@f%$uHgFm^)sk%#A)UNZCcE#MbxxMZqper9p|=>Ti9 z8P#d_2UoDlnlZj=X%OK%lEaacDU=Z@k<%%$_ip2Rjo2G=icXJr=-XSM6oS>d~gzLVd)XacZ(Oi_CWYyR`NUc_@B3xf04J~`5E@L z--0I0TH`Qx&9>6*lGkF>6D{`qQ(@lrSAEGW&sVY<3!cU-=$5*eKQTQ)AmPSTMyn=? zA|9nrJzP6)vR_kJ{!cHFH!YA9o*{Fh z_D0@B_xO9PLGCM>nO=MFU+aC|lJ;|gwe}Ay4TEC0bbE<5U5EP(e7DRU-#o3mk><%( z^q+mN66du8s!Jy`aiu4jooW7KaLZHCPHp1!$i&_JENb>M(wtXJ^>a60%wMz7<`$zQ zQ>gNq&yKyf&pPtf#Js+d=;-)5HLOMIpF;VC)t?*Bu2=ZpC^c=%I}Qc?-AtjgvP7pp zFqYpE^{qvBr*b=E5xc;(9c?F*ce~2{JSUuFt)U;cCqY7I_PLXupO2ITOt?D1>UX1@ z`+~0z>(9ldNU-j3W~kx*#lRx)i}zAX-)+{|HSE@s-BYAbXnvJ?b41r^?&5=+N_h58 zZd$uXp?sydrtFl7S3HiIYa2xLaW6{~laFmPy~QZGHkh-8!PHuQft&6d7R{XU+zZK; zLRE*Qq~*8pH%;RWNs{{hr3$NoNp0-rZ>*{9dsi0mFs!l&(69p`?m0jucgO8yi4C27vjRJ@I*ae zrfHDWlf|1An4=H&lsT|vvhwfdZj$OPOp^NdMe1Yw&F0g-Ti(??xK+*M#r7rY8_Q;P zv)7Gl9c=_Q%WpZy^`craqp;gXRaWGQ!SSn{F7Fly%+i&*``dB-nk^u2HkoOb zsl)pT4M!4Y?{GY=-tNWDV#aJFG23;)<8o2orxG7zuY0fBop}1312gC1%?e-ozh2}! zp>QU1gHyj$@ZIKxpBcH5o~Xv3=(SEUv$b-(kr&yn%9wNd(u%n@4zdapY}XmRKlocA zp^)cxwc`u1qO2Y4BG10uO5rcoUt{R!HS5@Q$A!maHFjK*Tlr|mqm+_w&AWE8o1A9c zHA8Ur$_H%sOn%*K>f6UCTkFrh(R?odQ|0QHfwhmg<)hv&ZtR_)%-^$cdg6i-1}^q5 zGerW}SxdIOH4jy7OTWI}Si!u&k+=2&>*7hLpYyB|<5=Tp$1&TLXMs0cq3qV~8gmZA z>4HkX`O9`b1FwBOWN?Xbua*24skiM%)jwqz{*tP^@Nx6ok8URYRbK@2zIcCg;A67g+0|V>Z2lmx+tLQgIe%W_dc8duA6t)emjJj5iSMquer&&!%x0zsmQuwlC;DfZ( ziVstzW&SPT{W9gAQvaL=_jLOg@sparodF%lW!_zQw(fw`nIk=SnyoaSys1x+U~N`o z`Jnst7e|Te^|#eLcP?Gxc_AyJxxgZ0rr3(+PYc&cypjLn$E7QM)ILr3NY(3~2{+l9 zc1gxw^qI!^vm!Re{q3Y%FCF}BHu$OOexKWy7XAjjrqd&cEklHL+qX$kl8m=+l};#s zdH3f5(IX1~n+#Tbc6@)4J;wWB!b9iPHzjT?EB<1!?D{_b8e=~L%dGkTOa*!ion%Fx z6g1o|WU?-cX#B0cBbjNpIO`NO2XWIwM>;*FraDnW z`B7u}vKWaAlVomt*nB!+>mwJ-Q~Cd}LvDb4uFOR{mJJ|pZWX)c$XK}X?4koP?5`vi zlm|EzJ-Ie_N1iSFO!n+VF9`b4)JU&u;my^=EmBq}bo&>MhJh9A5DOhuU*X z7KiH3i7WROke;)FPu%vM>A|OJF|vkHrFIFjdS8C)zqqP+B%Ocl9foLq+ZpcD9gNjC z+?+fm_x8ihN(zQglG_qDtH#F0J`mpH@RIA=MaHx94*XcWS^kTDh@-fGSNg^8M+}n8 z7d(zqYq1MHWWd5;`fbmH&uUc>yk9<oz{e@rm2|qc- ze8qtEr=+DFXbIx9m&~*0vs>9NI&YRZyS8a5cK|!Hv23N$0{xFp`zh3gh z&LtBQMJC8FF>n0O{KO-t_v6AX^O?*3ymdIgXF>Z-hr3gq-mht2&D?NW_C{LZgsYEk zbu$GuXCJl^E~w}7m?wWyA!0dq*-wRte`oA=P4`)Fj``C)z7lqU%O@4KeP;Un`GpQg z?c&NU%tj5Ob~!FJ3h9g)4{N`$$$q-awNvjA&xV_FQT=8Iq$Y0Qy|+QQ=Y{0c8RGVG zM>ouqo2xKER$+U>XKUSbdk1Cj=G+j@5)K9pnGdliJTp9HehKN{;Ni+S#(srS@%bdT zoaGgbeV_iEG~n9M%J7ECsp|dz2GegB?y^W7R9`CW^xF5zjv(GQ5wSOxcHH>Gcx!gk z`+ovaOFe@0ijO?4%i7f&RjtHvwkhCMT2gwT!?y#|sv4)&H~vuAes|6_#xkZiA?x*} z#f=T7UNLUC!t<=na+@F9!gJi)Hpt!WIpdfe#r{}R#0wn@CQp7TT=b7mMDb7o;1-M9VsY%o7QIT zFK;Me(8H9Y$Z$*k^UE)+Y!{C9e&JCJVCJigRNQFZJNcI5!nXMib9ukG*)DXen<{&G zfp39x=6artY0O)0{(c{MLQeHbByWy`s$j8=2WN-x ziyMhid?taHPAZg%rIZ+3{oQQy`1<wzY2P<1w9T+4{~C=R&cn~p2^hz z$D!wXPy7U`+Bw46JEb%kX763#`~1ec-wik2*Q+L+_@_K2ZpFnw>(W;urwk8&Ig_}+ zk1b~#w`EP?Pw8i75$>W#)StRl%&5zHSI$@(uH&&;~AMTzkez3`?8OX!y$nyo(D^Bu-NlXcQ|Nef1>Qbw+yeNX@?h!tM%uu6#w;4 zBr9*m@$FZ-BrGSeciiQ6dc7kJy1w1%ISb>e9S$?6Mzvb(V>9*PD}C13*m%vD?}hvB zLsm}3k5eTw_DWV7l-Ny}ETXaR;^EoT<|-sjGXBKF>tVa~GV_V^3o7JR^gchLvz7U$ z{%z4v~&Yrr4wH;rA-P5NwhnWVviOx1%x76HZ2rvH9TsK2&GB1<+Z{)fU9rE5TMeyZnD72{o(>kqh@*G%*{>#=MJvxz`;NL#j;d%WB-zee|!I}_tvoEhFs`nO;vPkvs_ zftOk}-fKZ!+H)b+w-^@&?>Qiqwn5J9MAVl|ub??i_g=VO^FHsUx9uGJ8C?U*sxmu= zvc=|dnUZo3e4kyvZ@A!g^)fHUn$No1{KRdoTNTP5Zt53%r;wU5BT;}k=rG%q{p^=7 ziL?nau_gUKUcem{W6Z8l_~f^@UG1X1=Re+^+?3tM_C)J~5ARy5q6Jm6q?mbjm@O2Z zrMR$k#p9@ZtWi?m>i#Dt*d9C05GB=?{h#Yh?Ghbf<hoyz%W`-|OWvrXUD<9kL)sJT} zZBSeux6uGJ^tvEFMXn=w{fkPb8xH4~6yyzk*7I5DoV~aTv_SSl8$-_j_Ad-27Yca! zc%NxVdzDWSknTHt(Vux@Tf+85%IA|F+-7GgQnvlRt|8Bb{U+z4@4l@vsrXO<(iAr9~?Y1W!gWv6_N8NUUFxg z+jO+G#7O7VKmN-Xox3F67|%L21US!`aP&x=g~#h^rw&eq67z;MZZ>CUnV)g|N&Z`$ z;`^3nXdR!h$v`MMUTxdK_<)FmXpQbG1DyD zgWDu!uRqX#apL90NP$~w+b{BQOg$_~GHXH-0cLvPgKnq3KDc zDL2Ed`$r5M7_R)hu`sjmYFW&5u0tY^Ur!O_(vEoE944!O;c3+Z>3xzCk0c#_%NE=f zJYc|dFfvz^?E+f~+XGw8JNH_x_2$1$ENCw#^Eke?FW5~ca{3@C^|k5ev}m; z>7T)DwXc?QLvn6rWj?Fjf5BpPP7nJ}A9wRCZg?cXz^l-}qgXQQO2X>}0lWV6%<^Qf zloVU}Y|>(Jv){(M_Dm~dJ@CT!MF>}P#B*j7A)mF!B)0jUexbZ;i&UojJWJ2GA1#bm zESPl-nOMbt`Eaf%X1XQf-+hjKjbdl6v-yriEM{^Sr{BGh{f$vXoby@CgVg*5e=TlI z60%KqO6bjuIXz*;Td@G<8U^!tk5BLVk!Ci5UrXWnvEm7PzeJR=Nj+pg+tBcC$B$WY zCk!T~J2-4#(0nMC#Uh36)_=xZ4Anu$I}iRjW!IC!u*>z|$H&JD3QO!%WktSJ$iF$= zyy0v?L*E)!R=$<)*DoobO+J13M4iM6-{)KQD9)a8dC7}HWh)K732z&J)*9#>cDi@n z@lBjS#4IKE_b<-A;4xucY^)H%5f|ayGixq?1T)v(MwUm(w^{t&hA_>xJeVe4^ql3$ zJN_n_X7*XOj`!1@G9tz8%A2LH9I!S^n0@!6^wcjl4>@OBI~FoVsdIIGU*G*RV9JHp zN3*w)|z#;QRvi1%Kst`0ZypTc>co zp&@T_dnLyeNyd#6tu;;CgwFX-&NC@H{|JV|UW z|AfgO);?rEc`-RiRfByqp^}OF_B}F6@jdjCUiyBT++jn!~L4#HO zy7~`ag)~|jF;9J-_&dzu^dYt^HkPstJUiQ03+y_=FCxAmHEIDLS4ZzX&xPTC8&A(Y zFXo>*q3dj$b+Ur_V&Ppm0{72w_~>hHR^Q-w?4lpX*Wia4>@7_OtfD6tG1;+*^J zHmu$I+&?r)DGLb+@hp%O31DXtll_`go1pfIhs)<*)g9v=-%rh3nVHV1>((ErbIgC! z|KzF0lrjeg#;*6rij%B07HskFS8AB!&BneecvJZ+!GZ~Q?7z-nEQ{wbOmxXnPch&# z;hUb7P{JuT(~$FZO~CIRkx$%|S4?bKz0m(Oi$_kge90$aP3bKO${Yq#*Oyh?@C;gD zz&7_&s>0b*2I_HAbw>dX4+m(mbj}o2JZA5_@bO85 z9>$y&i6^dhR`>ri-frNFf3#J8=fXHPzS0{!UC)$`G>PVT?~#yjdbsgRhQORhrZcQv zc$66gvi3AvX?(fE+_q1LC;GYY70;j5-Vb=V9FmFNZ_lw;EoXkVr13?~fj7rYCo>icubj)D)FgSuuu)c|` zu|fARQ>@8~3^ndD{yo7=PXu2r5ctHP@h&lU-^ESycU`o-#i(d#lWF+5arHyy*^G>) zYhG;K&bZ|})BM;4v#)2~WN_UkUA9Vi#l!yBDe5tEg`YfbaSY_qwm5NDr2ozi*L}}f zEPoy_YrI^=Y_ah2x{OHWhD-kwVyartpT9EauSD0sbP2Zx)*YSGA3izC_+4;kZ|Rqt z!cWd|o(O)SUe=iA@9=0ta@)#_jt94zr!M#wZqQ?35b>VrpcwChnY;pN%wAq=BhG&i z^u6ftHrg@Xj&*m2fZ6Vi`L6rmX?C0-=Z9H zjAb^s>70oCVsVn==I;`YAC_MWz3={t`LE zo<07o*A6O_@4V_^KWR$Pf93Of6Lz_D3hiC;j60?}^n!V^@U87eGxB_oZ!N4XG5&Sn zn#N*d1(!DawN~;kctZo6xy)|yTd{K8tb8CnfAyKnNl6!`zis$ou>Ig2m+sW?8#c_v z+$#imlasl*lbD#U%yf7cpinM%!Te~m)Qk3@1*zcQ|TzHgw-A&O6zhq5bEol0~zw3R9!L)@t{_xD=ZHl$($mW#S{F$@h+ujK*3T%zrr&US{gTZu_P>+a#wa`O-$v7GiN}vNT{$52_shNT#(R!86MN?* zi%KTQPGPRsZ4~;%bHaRHvz3Oz)eU}JZ#ohMk zNczE*b8-t({Z<#5NIGOP{GH?(aBIia#vL^RR~+2$l{ejyR7}6m`Q}*lmp<`*=h&Hh z8BXLc_#xjT{oz8oNk{A<4(|Jh56u3;$$H!2TwTK*wpo8KwA}mgm;L1x$q9GjP3#UE zurcra-#p`3`Bqusdl%gIoo|Y}$g)W|Mf^-_{;m*St^XP?TMnl2e3&cOdUo*( zV_xS>{*w-FG7En@d6eFMkyi5R__G&s0y2qS-RIa3D=@c6{ZOb3c-|~`{H)Mpv49U3 zvyJVl4vSg7;>a~q-}1g?#yQRtbwSqhTR3Jn=G6$FGWzj|Ggd#xtmVq=N9;vEB{TRr zPRQ>$pq%cwS)rwG9&2g9g#Onor2#K0Yt+|v?Er5q{B4);ebI&88m|7#H`2`59t)`z zeV>)U9sk5SAmP&q&`BW^kC&~s(fr8vdPCyth68_G&+~EZJ;nHik87L3;;;X>VtzYx z++;Vtu-SS+AG_(am_+XKfV+HN?9D$p>e>`R=L1G4Wvi6fUD(_EdWmM0$&bQPJBK`( z4%N&J8xDp(e311;NI2|BPS^ZR&sA@5iqHF(xZ}eY^J|Ynku;BqT^XfhpcJ6 zFFrQN{5w+O)6u!UasJ;O4EO#sa+zNU(z%es(ZL%xi8bYe)B8gWA3v4`w0(NRxq_K# zSH*{yTUvQ$eg6G2?&zc24Sre5@>e#fnM6DB@;{3D=bGbwGWlaXTL82Cv#@~3hW9Ks zU!tE}{Q2e0f(uHGJkyS;uV{99J^K=9vgG#JXIG+%TD5t5@AdfYy<>Wd(UIFbqM5n& zB=2DZrW3u!Ig5WX-+kc}C&wJU+kgE`{wL?y_nOb0e91Dh;FUG=izc@S_Eu2m{)0qM zd0oSu);WEhU+q^`u@!w|j-SYUyNCDnga#{hg|8=MMdFrp|7!aM_QCDnipC7p4ilvB z-|(BL^fW~?>zvmEZ{;WN><^Yki7n*gSg0iw&z}15eZU8{$_slnHmJr;IkzBS_bEBg z#rLPoD`;KK?EKb3v23QOqkz-99b^S2>~@^H>fjB=Mpxq%7yUEZ z5*4fzcHD9CQD=qP`R#0$g4CX=S$7uc-B6CP+T zaQtIap8fv%SB5t{kKC#8^I}gekrex?we=z&hl!4R(sO28$%9fil(&9vyd!zI?1{m5 z1~~zTjGN-0-f(vGt}bR0Qcny1lOX?8^5kauDPsSZoS7H%?<;H0+;m5?xa`cG-=9oh zXm@z;;|bOQY>)o&$NaYEFnzW0la@pP zqxV_qd5*kG8ux@uxWZy|$y$EF2d3U7>Hc;H3ceewJAXQ)&eOg={t$;-l`iYyt2Z6* z|7I*!$k@hpz3|Wr@7)eBW$$;!ZkQbB_UV!~TgFaUV zao2s8i;RqSmHz+un7ku-!(F9*o5hC=xK8jfo|re~2P3Cr%;^md=JT8LY}qZj{yr-< zu%BJ?T&P&(V@8pZ43qLcW~SFQ0iQ#dBOVKGsb{>uv}wt_W6rBtc#HKjuGFjO?RJv$ zW!EkIWF(xl;JfaZ6NTOPekvSMpQ1OxT3uo530dx(xxzO#=}nMXdYqI0s*^;B9?vyC ziM5BP@Yg(=#`xr1hp4uMl697(go8we;jcHG8Nn7OY_I!^H_l~^R%0zz&Uw$dqPS^w zv(t*=L-W{jZpi2-Io!MKbiSl@4!_6EaL4sa!*(2Ey1RDCJPA_~>!2G}8XG=1?q4E! z#W9l6=e|K@l9k4So5^2_CMLEt9=!I$&F&-DOx~y}*66ye`L65 zaP{NjBYFoHJ>6vXg^$Zh{)%H_T3TAe)yXepr%k-XFWFPAz%jSRwfpR=#j`JJ`hQd| zV`G_Ckzx4RafPDGd*QhSs*@XE)hPUyf6{i)z?)@NjG}q1eS$;$Gnex}m`YD$$atW0=Iig%at9@9@Eh@mdtJc*SNOrqQW_k$e^~m zZkwXx(%TgOy}rJlhhNTyLH)Z zSc`=F1iW@xb8+@XP5q^ADeNs`w&8h9(o=T6+|xL7#uCO|DFPu47mA-T?=|dSzmcD7 zvux-yo-IrpEN;%%=8?NP>5Sbeg9{9I_iy;XDC^6!Ype7X%Y~us92Ys2Ww0SG|?TvKKT#+vySaz0My!)%5ntNC(=1PpR|EYVz z6QUhY?@sXEy<{_6TCJsq?%_)sCw!ln9Gm!cLbZwB-czbEc}t(L6|^NXB>ZFuF?;dy zW#en^99fYkw(38uG+xMxT`+R4ncl{?l<$;-i}|mk%`fs4RQ&s9w^zC67^IvQ+|JTH zZ7zRA%Odj(w&dr{_b#_LuWfF#`OVyAzLo1l+vmnPe`F7e3sU^_fnFtd1tKKxlh_{i5x5D%DvdB-y*d8!t}0-R`CM24W(a9K6)ay z&gG?Q?}p%I4#yMt+k%(2{W8+YI@`o^tU$u+=!cG(jE$-yQ9VBv_Xi0ZpR$_J*>Z0# z|AkAE6Y4p8?_ADGk+)srZY{q;ktr+YLh%*(%1rTJZ=`?i6aKO^_C)Z%BPD(uvT6*k z7AUNiocp(732)J~ctf6Ihu*)^i`7#S{Z&ppWV+Q}^y6VYo4_%R-HqyTyhl^mW;-%o zTyT>|*2LdNSTu=2_h8kQWP9cpE}AzO7;+}tR2(~Uu*XqPk7bKxccYj)&t$1}8=h|G zQI=?UwfN%M7f;k11Pz&)vaU1;ajw|teDQTV*lu-M4zH)E&ig$&&l4}-(P zju~8H)W~o6*48K`_2rI(U*?YBS7BA>8w6g*-%zWJkrjz5|FFXLQSaMhg-;~;X4tG~ z{^aA+!B})hmzjCvbdyW3W+cwoE%7~9B1By5u-WX#vmPp_`1|c+=6%uh<>IS`wudon z{J;4))>_NI@GiR`%)QtBYvQ-$*8&%JH@4=gaons`_~szv%Hu7(q3x(gUJCDYH}i$( zI5qkvnjcNRZDU#WNmNC>M{mE=6pkH!2M&d%J;-LbyqVefij~5NcdWAFJcqvQxI1Ug zruo;NvaBiOf7OxjdV#`j$!n1Z%bLVJWOMwvwkfwcetJ?C;NX4e-g|qVH#HxO5^kID z7n^5f_w9)_wdfvrcbtV7{YVdtbq_GBcvwA>--=nKi#9IZE3cI9aY3GG3Ny ze!PzRi;H(Z-|YlTJN{_)-g(BEU*f8c8aOb7@HMP)+jpO(@+ZS5wd5N-F9U4uwniPi zef8>52CKhWOX4rJ+1={Bw_7z3!rm&!EP7(D zK+I36C2cqUDjbn9?3r`F)AAtq{TzW$XJ0TEt`gri`yA)g{wXCMZuxHN>%U2ElNE?~ z+;wa5o#w5d8N2FYddpMHmCdWzvu0j&$U7zPqx|p2p~eeq1WnU>+|C=OCp47$C3u@$ zwAQ|IPvpG83C0x*nPxF|_VlDkykywB=0n6E@jd#DGu&+Uo#V9q)+i9Qszo=iaBc&u zko*fav5j+Wt6Fqz4>ir;<1qcKzK^f#{lDOZ)l1^`GhbftG@+@r%y)k>h>A2Pu2r-A$acwjt>5Dp zb?hz^`}B1tOfTzgId}5KC+$a}Nl`GJFGHmtUQ(TgV!p?gR$jD-CG@4xcvgac$nn7@?bUpNn}eLx!Z-i)qCZ zN;SDpN_#Yx26$ZT-xJ@HC?X)rboiZ!PCzo#m4F3T&#9G9n#mh%Cq?tc> zOPzn?yph91I_2+s`DULQy%-sj;7{xp(M(oG5-LB6uQ{;=EN4-vOHDG4kX@TUaew_U zL085{b8-(KnBY50aDku13O&h_r^`Kgza*N1+AtT2TBLtES$sLL?D-_M9PiQzZ`)7W z&(HGR9<24DmA5G3V)aY$eW|_*SF5|4D(rXVfRX$^R z5|(23>uL9td!sK(6(zrQF>f zznV<594mz_uWA&`TM~Ff13n1tif?H2V~Afof8JdFn&WSk?uYoEo_)5E)iP&2^RLuq zg|8<*diVDU{@N?dQ^Mw)`%=_URxroWBWHP$g5N%+t;I~A>1f0%bBO3kkByz9mH_pv#efuLe-~s;lfOCh{~2|y z91FL7H)X=D8cm;gTE6W{WMI(A{Zr1Bu)wvwa}M9BJ1tLn>f;=kn&-(*@CUimtI>HM zv(xIyH5q$(+U687-Sqt-6~Eo;i^Ph`he~$a7qts3+S#6Vf6}LUBKF1Ho`XWiTcj>6 zmOjt9T;>g2gH@$eB9`6rTQQ9FgFxwk$36_PWT*Xbb#7k^dhrInE_7m9-acssCkwwtM@KhDUOhYaL*#_qmF^qZIM?xUsir=Bkyi33`2GZ4-i>E# z7WDHSnx-tc`(^Qlo{q)t^5zrW-}aT+Nk~kPUd(oB4NqK}zT~Rr9|lD%8TxD)H!nN9 z@l-UeTNyZ$=PH}|$~yIJ%%J-6PwFq+RaYq8z$F|~m@IuF zQKFHdBv5tZ@4OW^9T&O<@SA-Xc&z^A9P67I2~U)pIDdA>$%+K*YIrK^^@zK~N`zza zY{p%-G9@j#>mFxcwAT1?Y945SxKD8Fq2_7-9OBwq_t>*+^XZ-?D-y8NyZ4KsP}g0> z>x_-1S`HI??3y~WO9X0TO{<=AUt+(l%#gK(Z&}}ofEP79(|VY=wFBIFMCOan`9--x&X<f=<~@}?)TgWioQH;aMP?Gp+sE^-;wpPDy4VX;GR`0FlP9tEi@ znv9%HH<-6Rl(}+2is$q?hldQaEE!~#xw(s}-&({RT$;#>8DY=wTky-5qS z6jHw>Ta+C;!Rr&SbH&=Vy!XxBPMzUA;rHYmr_ubx4yFrlju-gJH*a)y@p|4k>3776 zsVXb)9yoHnz&-E9VJn6gvLaO`e-f*ME*uuvqVneNzrzO}|EmmK^5Jdl!g6=kD;pKk zjI9i_61?{$%yYfp%=Bu3P2Hav2d`hBp16g%$^JO+Og@gCbNQWE`%=CI?hrcR>2m47 z=~p3=7pCj@u$B4zYW`=?U?#C}zKio}7q+YbMfuI$YYn~6r-pB6aEjm7^3E?umVr%* z>B+g{3DHr__cYw>Ce66;M$EK{r&8DYumal-tE?YZqEpV)^^`dXbTZz5+WaHUZ^K!g zW*^tMTc&rc)OnnFc&0}(wh8idyq&`nBG5RkrO=(l$foMo6i4Bcf(GS>zpZIlk|4X{ zVBIEh&BV@Zey$a3Ev&ek>{Z&2Xhtk>Q{}k)DI>C`SMtkVrW138Q_M`w4mL01ekNAq zzBx?C=Jlbi`^J3jGYz`E7Zxw5zoUZiYoGL&Gj9-J8%qhxM*T-yVL( z`L!*6CzxI?J#NRE^IM&xRoJe)cG2OBi+-e~c5oWcsJkGmW}P%MbKcyQg*t|&deTe2 zx3<36EVUpta=`&MUC!Mp3r-qHe80+jWNFI+gGSj&E~mRUwpZ;nePONeIKjZcIGP9X*4`hj0Ige&cDdqs^c|Szykx&-*|>9lKos-O%mvm8M|KGAWOnZNliPYqD581Z9aT?eP{C_{LRKVZ_AALY zO@^n^7jizlIQwFUaz%jtL8jEA0F_IhgKQ%LCSER3-4erS_NzTt*yhB&4JWT3ye1q~ zRnZB?a5;tQL4t>Lt8la^vaV zCpqtyrT-R)mv}f!RkFiYcf;hzZnwBt0^B*nmvjEL6A0LKaBDj2v}J6Umz8EMFAk72 z-z6zqzk=_Uq(B6y+ZcXA`RbR99f#bQ5|IHpr=+;0>*k+v=V3oOz0F=G1*`TJI-BH3%Euc3+#Cy?C?yjE%+to8_m3d}&GZ zb4Uv=O1d6!()!0Cf$(OTEjFAjo^Ks$rI@x`U#@0riAr>O$-}lc-NE4{-}Jdh+DzZ(1bXY{ z82!4ZQ*%#N%h-u$F+)Dbgk73)mCiON5|Yf0@?W2v&F4J5XRGWlcK*lf7mF+Ny_9LU zQ8v6F$M{q_>D_(_5A(-Xyxc15GPKzFoLr3~*`DV}uVPWx@o~uAc~N+yL37E4vkjoL zb8BXaES%zcUe)@D&T+<8PL9LZgoLD6m!z-=h?yPf^ShkwY`V?j@YaPh*qOdT zXD`#v+!eVt?&pfHygSi*t}a3U=zFmpkY`N_hQbzyHZNYk6_jn~jIdLv%M)ciM7x%X!cGa5h0;x8?kMn-xxcuYO>a zC4PIZ;)z0rR|`PH$%a8z8jELNEPTGl(Uh4<`sVU)LdyNyCi5(4GupP);)Sd*XaU|k zr7I8EbJw`ZUsN;U^2k`vdBQI#-M65XeZ@qMnT-|48*Gex*MDdhEqTHFw((U>!y%EI z?{_?!cFkD+gluS=BGZRf&RsG^&s%P6kdduD3_c~RX9ad^v&Yf7$ z$8R`S>B7AU&x6-??z_OYv$#oS+KJ6-3T7OSt=7w@uq`|$YiphLqL48wrTLD<3@iB; zc}K3^T$;K|O6zpbhqDC}wA-~~KnHC_A3V~+u;vcSQt>a0245u8C(Jr{%TjXX_I1sF zeBa557Zr2pnn^hOb#)zor4sO*Mdjo7H>_-5__%C~Ek6lqefe$UQ2HrheS62=DFPzP zUTjv~z{jbX)^KXt#j`JN1ix7DqT#}>&y8z0_SiMq3!Gl(5ZII(YrP_Qla~8r#*mYN zuUQOgWQ8YKCu~+bA#QwV5>Jk@!Hau>`Npk`xfd7cyC+LHHB2k7Kfv{OVVM@U=4Sa5 zfxcdKva7r^GiGjKfAwYc!8x&xvb+J#jCXsFoU>^D!u#wT=V1f31$%WC_;F;+KOHce zwef5oXr;~F<&Cd*M73D_<2&WxW~{M(!Y+Q6y~4%;@7(99DlTny?5R$a-F$Huhv^o! zEzC^TiVU|i%$9aexUtlN*>F<-YG;;D#-BE+UHGIOr5-Wkr@^n+NtqQFnjf*3Fx$Mb zV>{9I;5E;J$-5l79I7UX+a)geYA5h!@uS-h-?6klchK7_^`c64T7TQ2%Ew>k{gvqQ zzLYU{p4+WY+DV5e&snNGrNl2GRii_$<8h0-`2zlRa*`Qg%q{ijqB$y?X3!yjK}tHyoJ8aPd)CQl66kZmAQg zE-yNzpNY-5{j&C=!nQWWH!7N6p1Lg9!Ms!ciY4Pk$656f4$_}4Xb0WMP+B@yBjUyZ zv$^^fKYJN}PTDo`&QFHcp8=6ot=eakwO^c^E9q#Sy=3m?^9Eci%tq(t&ioN_{Df1T9UL` z@*lJApN_+q4i_!DR=XTt6EMl;N>TrQFndsD#O7RbQQxJ&*p_v@MqkIIU3cx9fn zeNB+lls|Efec>O6-U8=$GaBAFKU3DXcSuui=k(a?d7F8U-_oad<$p+>XRh?;GVN^Ljzlt1waB=v_aRhh>jE9=v9^YBk2r-;R};m?_()myLqWHV!K z%Jr03xThueTT7g*x|92-Nku98>y&E?TWxJW2^|(-DtX&*z)axsqR))n#YyjfFL?e* z`^z!yb!=jLr^gD0t`Lqm=hnNWFK%IzR`BtY`3Kz&=e4o-3M^Vb`PfxWi4!|q`T3*D z{Mw?FrKg!+oc`tE>pKhE)eQ@|wbR=U&6B9QF1lD&;Em$H&J)tz8%>KQN}vCd$Flf0 z+mrs2;uR7Oo6Qs~C3^2kIzDf{@@UrGh3V`p@pTF&zfFX!6c&6qcr8G_gO6k1%pTBL z9!-7Qcy@eS&66TM^Fposi9F?J=LCYR6z99;ySaB(?J9N1xcRfeG=anP+lErV7Z)Q` zmj#;ySm_`{f|bGPC+!|tClv#mSMu3o%Zen)blO01oSSCpFS*#@ayCwdJ1fn2Op&mS3zMc1L+9 ztlW5{Yl0+?3B!&zEv4riq%S#MQ@StPbXu}GvDiw}(Irnk#e!EZXx5U9dyJAN4#@HJ zX2b}xWVJ|oY&JSFyU^%DwMeyrUa&L2dXf9aiPp*r#)YMRD=r!yoW3t(=C`&>9QIYu zn*$nMUryS3@h1NrMVniU2W8Ec^m#S;9c${n#J}uu4rghP18+r;wfctYT?q@@AaWD`Yrt-SL67!BOB)Kar263I+VU8;rP5t zcmMr|VpmM8nxnN>YR40?!#k{8bKCzJHW+N$xj?ziu_nfyxA_oTqAu8y2Rj+E)Ekcz1zys^x}MSLdAzTWo$i zcG*w(9<5OB*D?3z!O(S0cN*-Xo7U#E?krvK{S)uB9mluttkziSf5TSOCcwSlT z$c6ITyJglb$emeL)*&-o( zJlrCYTl~pW!xPHqzm!RD+U>|&U$tD?X|vj-o9+kwj$A8b_H6j}p+W2XD}_+Ds5aR( zpABWCZ=QJQ_G*)E#4pLYe-FemfiGh7^Xp3#NoZr(sy|s;E3s#7vtyn*+w}RJb0@OB zls`FF_(_}Pi;k$A@975)RTz{8e0cko;cDjsi>Hbc6epaO;F&8@vpi*Cxu1jdHOGqk zR~GXuDT#6T$s}T?T>Gu(mF$Fz=h)w=hHhxP`g!HGlC_IJl-ecm?r(gvL(yEpvG?`C zD+k(2?Jii0Eofp^W8W$GPqlgVnd%MU6Wl+oFkR(-dgj7|R}!4w*YupL3s5hUv#&cN zASrp$fXmG}VM7ap>RjOo@(GKNGg}rjNk3iw%){(S%8H6L7g=7pO6Y?$JW*wMTBQRU6 z?bjvkDDfUp+2>qQ@>BHR74}n`7khta3%}etYp(Ew^BJMf54rt(Ikk?X)X$-g_3S*J zX*XQ%vm4!*mUyu5K5MDY1Z%|~X~rK){XAx}HZGNI6XaQOiIGwC!G@*AQ_@^6sAXOV z5|8mVDwsRTc*5y6hqA@uTQS-$U zKN%}+O+KahemTeSt3%F1*VO7;^WHhm=ZzO{mcP=u@#53)ABPK<=pB?=^;XVluJDBY z6WALjeE+`iyx-+b#ZK=(xZYVQXrB<+T_+^2vCiS4|0yG#Dl54?<;t^7q&w&8DyC>@ z?`E%?VPMWr=?XxM+9w|qE#P2-n~ zi-nysmNDPwuwTo~n6lfEH|N4!u@~2?rc@@mij{ zc-L|LOyvvnv?f?Ph-w!-wY;O{{pE}2sW7|SbLf>fe_P$~ zH_qId-V1vNlaw8GVwrp z&%1M(WGOg^P)hgL1brF%gN&V;MI3$T|Q+d<8R+4%978B+w>xmaK zWjcBKx-->RQ8hBH?8X&$ko1OdaO(*F0>x zXSlFjLaE%&LD@$wm;Zp@fom^hI?k!SS>!fh@dn+M%HPB)vs$#*H20s?Nz(TI@-*he z)B_1CH8{_zJmT`6aNjN6?!)pe;Pjntp`X3v+r(X8R%v^@lo2$3?aW*LSUcZQ`NoNt z9DC2O-t=G3s91CS(IumQAI|Q1kd+{OE1>_zWvAa$*l$Pl<^B};wXFEb;_`{HZl^A3 zr_?T}lGw?7+MtQyq^v-IL!*(j>Garxhi2bM4R5xrn;?B-aj)`~8BToC0ai^hW@_*mANQ>3PSfiUmkBaO&sk>ruasvy9mjRU zEj#Fs^Z9e^3vFed%;|9Lig)~IA7s9G@)gF$Qo9u!SiFGwrhuyXh@)wSuYLC|lril}q54jk&Z(#-5&?Dyo! z_KP?94=rSis!PrFy>Hzv;dXEVCu5dQywn->7T#@s9NRkDOZ5^=7M|lg!E@uTr1Q%o zdNtEIoBr5^ykk~0{j5~(HzD22V=k}c%Gnn?-!%km{><2w64Ptpbo?gYlX?6#oyA)| zH`>2G^er^U`s;*;hc4eQIQn94|G^t|j5`JQHv4#&^SL~pH7QcqrF~K(<8{r_9ad^L zrtK6I-qsY1yg7a-W z(^S(IY??f$Piosa&R@FEpH zCC*5{lw845@hAD9TB7wiv1^u$nhy8M7xkr>d(;?|_!YcmPLxn-m~@VL>mGv}hdaaq zT|Y>~U0~A=IMCDbm*=7ykm?_4A@KL{Z0Zfqpd8NA^$uc%Ha;Wn5!; z<~L#9!CO07cJ{`3A5J(P6((qP7IkC!)i zmnG{re3Z7cUPr(mAy6@>h^0b`?5qMK)p5Y`1Z%QJM09G zTTYf*K1FAt)3)xI;{(;Xu5X~j zYcpO+loc@kn#VO^Hv1}OrxnG9cc#Y$ZvM;To!k*Q*<0fnXa~T7tCo#ZO$~T=xV?1) z9W5@A@g6j7dgvjGm-hmr&P0)(wgU>hj85vVe{HK7-xPiEW=Oopcy@uu{G06GWsA~T zR61;mnWFnRqNUtko#FgtCop5F!pDbu_*C>rk}7OUUK0U!UVT4)^bM0)A^3Pv;l9t|BqlQ(4Au@n)Bn!x;vB?+&N= z9Y}q9rf!iDOV!Tqdy$H1!8X6-#FBL6R(P{-+}SI&Sz*cyLy@#Di4`0MX$}dD20_zf z8;x^xUcK}=@sKyWqlxQTV-`=L@WXwLd3O#U;wihSP<43LJY((~pSUw#%53~zb73*F z`4y>aEmjggPHE&6_U8-RoX`nKX9+QD)N%|sEU4n<(|W>yiE#z9kf7i}1FnL01|8kr zwu>1Y0a8rOg(dR$&v5GfKa^&dU}C9W*7$8zO>ihvwBpVhzB^hqvcfe*%r`9^_y2Fc zF&VUpS9t#704s$JrWwtd!aBO$?q6)>6?S)I?l^2E&um!Rf425T67$`k4LAE&e{Pgn z&TMIIJmGtdLi@pj=r9+r=Pdz$l*7AT%r$u;Xf;9RQxB&`&B<7=0|qUO89zl&{9IgZ z|H1vy3$~I+LY5l+z3(O_N_=F9f6gLeaU#|5`rGOUADkpLnC3lWot-$*ZMW#$fafjq z<_av&IkEBScYoWohPxen-8EnMII9*Zd{=TRDR#S*R`Nq=&BSXz8|GeXxx=8e^)ut? zDPOeaUYNeN;f?H>x%@GUe>E>{ZrK;Y8*X!{DA-=3$DuM`fzLp}{I1Zegaq&92D?38 z&QaLiKV_-HiK&WJPdn_go!;B{yxx>l@>8@>(Z{PQN#Y>G77^*a2Ty=k#+hNKP1{rJh{$fc2o|m96W?1UM%YY!c>4142L@6+shf(o z@iIG`ebZf&CVzc^!nZiLduW)IUA&(@ZYaE-thWfPh-}d!*5z;6E-|}VqRcy=#JF|Rb9j0 zw5}#qhQrR%#063&UGBSV*0boqX|W_>t)bhbuY5 zZZE9oQQ+a~omdclEJHr+MGM1}D`oXYy6BA3Wwfqrb)UtQ`E*fa=E~quxahu}#w8J+PJ}#_t;5_ku zff>_^HB#qti<`s+`@}Bs@Gw`Z7#c4A#(ek2@#k(|YQ>nZ{y1LtfMMGf-cQ`NcQ|e> zFu%fA?O?xchMeq#gL}g2H@r1{`RY{?!`wR4U5v8zYfXc`)fa64)5y-UZl-`!mRrA; z+B#O2Y#qL(duy1lZd+VBt0}jvz0~8v&lj6-G?#`|t1Qu+c9Dc#1q$h6n z8Jc3-lv7^{ZZ{}zNNabHWHVXRzptlr-sxEdKWEY6n=hclihZ*fx=VY*=@dm?GEqDK|SfopI2+hiXKEcp75 z?a9+vh3gBhZ*KWESK+(`Ps($a6!V-7DLa;}zR1ThZ-(p|&`w6j-W`p3H@ z=JsD~k`!Xv(9F|zn^XMAy_HU0RuZdZO()2|+xhPp*p3OqJ5@7>=xsaE~Vn>h_{7L}&wF1Rery=EeB(TRk637+p8q~4rf z_d&OMQF+ANl|cy%sbV)yhTm}8!G3sO_rZXQ;9}>m3F~__?)IC=9PSF+thV6tdhpZ? z<3j<7mDyhtH_I%Z%lqoNP{6*nx%XUrFFTee9I#Sse(Q1TVZ^n7OO}kS>}#5x)^7V! zaKGmq(NK0R;tx0}R^B9iQ=j4Nl0I>h92-dwAnLC6Tzr>M<9WUs)Qy zSgO{H<$ms?=8gL#^Oj!_d^M-xQNtbK-3fCiB;I5^IMrffsm}!S_Xn@ZtsLbHd$?u07$>35BKm}C?gyqpiOUFdQ8#4`5?Mg5b9o{HCOR&G|^ z$Uk+d>jG~U&_P!sXHyP3vhRD{e8iz;>Q)1(`^zexY?4ah)$vu7H?*0<8({0zz8&@uBJ08;WV9B*`vv(7l9?h<_xxvbDf!`&E zxjb#}o*$gBtu1Jw>8>dqKW;F+{mU@7u5}%Ad?as>_nA%66Lvi`du0}6w!pZjDN&kf z10UPArD4vwYAG5nLNCIKZ=8MhdzqYTq0!R0!V!|*KF?Duu63L2WoM~9#uD~&p+3LF z3$Hwbvo#GuPZIVX;lIA-OhS?VHc5#T!x_lpVduY+>^_DAT%VxKz zjwUMw1=%Y*8U*4ic~@&VehHXoD!KQ1(~mE#(N7JkwzC!{vPthp3DE}^plGllW^=;dXC8+){x+3+|_a*AR?<(U!m>MC%c%r+(}lNC$c==E@?OwdgH;J0{#F#9q4u43yew-^^cbdBnH7**%`w!&R+y<^&AtA*U*$61!78=RTd^DZ+%g4KkF zF+i%F*P@rrtBoquI)LEuW)huLt-O^L$kTGGm$4p(v^%qX8yps?d z#k|#oE&4c9{PW}m{(G2i^3OJM?f-Z1isvCQza44L8L^%`S5I+lncp6F`tpUx2`cjf zTs*C0Ud%qI`JIbMKlVIEC@U*M02G)`>HP z@AvT7-r;;*!*i6a^!6`n9)+Hm3m2>ApMUX&{pHnD3HxdacAS~jW9I1YoM6JTLYxV7 zW*|di06R;FTf?oy!-d7BD}TFn@FreJ_+7xIKW*WxogOb|EI2>mfK)rP?bO!wpA99Z znH;>tmUEwd+p#YRMe6%z@>T5;Hrs6$@ViUnBU((I@^ZFVt9+<%>11?FF{6S(14ec=q}_cQ+-Wkr6ZIj-1h zSi3_vI$1K$RdCxW-pYE;oP5q-ZE{s>1J%;{k0;zN;p4K;QD4ZTR^D{Uuy=TZx{w11C5bZ`7&}nkpj~uPPmgODxD)Kn6pH5Z?eqlba> z--^U128)kQ+;ccntYz8v2A*Y?_^$j^*p}Gw-lpcpCf%$vGkCUjvpIfj-NPvPcavj8 z4d1jrp%bz#(-;mOnh`f$i0^7OTftd5!P)JJ4|#(4XNfw#b9iiAUGlB@OVFfQ<@G$z z#Wc6g%#Uzqsr>mi!D3;y!7=8Xtp{E_VEDMv`AnQ=TVR6_(*}dz??nzYyq|Qmk;3d`9i z#MLZM3uRqpAhYjdAEQY4jW?3H4-9&kq*@q$P12hnx?oG2-2s+Im#e;2n>2ybE=M~< z&bMTPdxcH=c(|WPN1Z7UnC#bf+UNF$`HTy{YVa+*DfEQ<_XpKA2TNvKXq-`dUwN|N z;miCvy~hq-;B@5ocQW?cASoPmrmf)+&-J*O2je~p%=)WPwo}$Jv*Jry)}>(g@NjYG z$jF-+)om>T3TY`)Q|cYvn)>FmUObU%{i`-a;b)`Wk(O(m2_+`;zX-_9HC3`blhD3R zL(cB#hwpD#KWIiaf1PynV1c&PnjEI3ra9Hc?LkKk)>tbrM@lppO-=b0SP^w&zBW&q za(K#%xsw}nt{j${xxj6S(fjhYl{@(&E*pLl(w)FG!>(%Q+&fR>7f1@<;IPrX!?jyE zRm03{#Z^YerR+h6%C>A$+q+64w$3%~t5>GGcw#iOt)Z-{HopMpzX!17p z2S=)xc{L_3&@xPN+rfUChu2V6uByDNt!Sxp)^q0j_xOUW6&7!nUo0z7WwI^v<^e~& z^Nw|rew)=6%TAbhd4}8zzxM^+*-Og&PQ0AJbG1*pC`x)-wFBGbB8e}8iBC#TZjcn1 zAQho3CSs{z_UoTeRNj=9or1ONd5Rv3Y`dPcAnycQEBB`Af>NW7SUs1uOyVNp3N|9| z|0syCwOFaY_~kkGuf*Noj&bZMB|k+oAG)2E-h1);Ooio{PtI|y=xNY>>!g3$-Ta_& zPt!#K2_r>@S1}gpw;z=1N7za47Rs3`eBqK_khS81P3bG{TN}TzQfOZI+3}o)ZP8KI z~5MC9~m9pZx-6-!4XhZ@*(4R$_v%64=-rQbOgwIxu1SFyJ`w!i{nF=b7xrho#R}Y zXn)0gG5>1569KPl1iW&Ngd}XZDKsJSg|uqt-TnssJ1_Rm=?s{W5Y1!~AgdbjJlUe> z$>Q=G8j-VHHTc?#mgjEyYX8NF!DNE*j87Vxo7HZx&Ao8CD(WbQZhD{F=ZhH}JXZx2 zo(DNa{VZK^pVKJEN})MXlSk87egTW;I}KY?YqcMTdheZ{S&$l(^RUZ~+bMthp=Gji>BT(b z|5_j|CMyu39Odks?C@D{As=he;(jsjmV(f@1s@t&d2)`im_;)^65gdaBkuIf4X$zv z+detyDodU7UJqK45HFli@>8_3kV#5IA!HwKE8G2mnWmC&?F(xe zJAb9vQtw@DpL9-4c;9fqZIR>L{>E39%~Cl><_NI{HP?BY*cw@X`ow(X;{N=JYwAvK zu>Wp6ga7pmh5QNfE0{X3@JZW#uWh(=t01Dv_5BXnxql_r-g_y@q?{;u@x_{x8S|w0 z6b+_GU0R}dSgCCCPmkL@c1x@k7Mx?x=zZf*X6LbU;%qVT2NR<{JlHk$R-w@v=cX4k z8v5ASWT$d%YQFPVb&5z&iX zQatmwC2iUZ+tnsA(igwn;y1GT?HKpfXxE>vKhI7i+-|UokP2J8S#3*q=S4p0%0zCi z?GLxr^h(X;PI4+Ty9uWgCP?QkiMi6gw%Fn9BY`V38A>Z0(iY7Z zXwBnS73WbZ_i}i4=*N_E(*&{v_^&MO*x*~_{PtK_#2n@OZ2mq~&hr}=m3(7PdH!OP z>80XdFWx?XGQDr{^w>$_WgC{B-NCkS!s&k(t9=6wOGMu=>|t8ul&~V!gX8vN#!oWq zYUPfsV0@__CcCadrfa$--$_Y<2nYUY=h!tI70#C^s0-xurbfLBRapAD@$}szyZEn* z*l$hqE-0N>a8~Q$t{(PM2ew}en7#gVI zcKbmArXy!&HJqvwSoU;o=;D=$KiUoi+zasaSu9lEhFSZxOvY_rvMhYp zKaTpx9=)nvX5JK?%b=rsBcCUK`Q-TNP`=6Ci_6Q7gx_n9VTiuozxqu3+#s`EC7D~Y zTj#{JMP&pO_aFDT*<-iFN}+k_=SKbH1?H17EpIozcT@n%w z-s%pblRa-UZ`eG~|L7jZS#gQnt1R3vaoBC^GYoUn<25{bK`2k4x3HB=g$dkk{6Jj?46JZnm3yQ zT4`-`)I&^x2oY=P$L4{qu98r=IYJ`I1;E}!v%VcYzK zErRxYoD)FJ{$;@~96VbkRi5WacRb!~m@Ih3Qt^u6!e?hr2E01Jd#l=k&HH)trQO18 zs{&SnW_b@?zR%JhF8g9>_=|_lZ=GCHOs^E^e+scXks~1=?VeKdQnXT2VoJTEmHXlT zJs+g^{%+nhso3OiZ=3u+fdirJ4PO+lGe6OLF6CQ4W$FHf70X#I?bMbPH@&VCtog<} z^@H>j*$Is=Y9<&dH>{p$6Cw3^!H2_Uzk1%iJ9zEqf$0l3$nu_cNNw16Od`$3R7<5z zkj+iMVX@Ak>H6_}c7LnYqfbl8iUWolpY zYw+@3;k~nD+5LkB-hTq}@)w889SQMp{gdIcr{0w(%1TQOr%at{*u(V6i6MmT z(q=x%ypJZc+6|MZOoDbC>_3gKm?!XVILEoJkJIC*mJPQWWjcilPGrN=+>eY19C+r!KhRp$EMjeDOYPmTAg z3GUO`FJID*khrv&+5FBbj)=!I@BLf!?62w#KEDIcQq^zxP|e%~^zme|NPS;;Rr&F=oaE)6l5nfT4{;x3~bFVk+^R(?clYa45Dhz3m@9d=>GKZLcz2%c3gaqSeNS^ zY?j)x04sjSi7AAYWTPL zsonKI$fQ~l(7`?Jui3oD&;U)y}!+-x|d4XQZ|J1T|Jb#4Jm z=$6IO7bM*dW^hc9Woj7c@v9mg!$sjxoj*~0vJR2j@&V@jVgP<*LaalzBK4~ z0l#~Ywc3UN*ZFrH{LrJ) zg72!NKv9j~>Bz|orTR8Rayxx57ck!4SSO=zSq?fpIo>Ao5mN}-9uO4>1*5ePd5@MC$4!o92VZduNY^TGA7Nj5`rx)ssdx#^S*Hx|*#G5NE|eoXdEz$7xyxh)0-Bf} zUUV~l8Yx+J^FhW&k4TP&OUf%I8cpHabWq~?j!$OWPO;Ti$z6XMsch=!=D%M`_o|z7 zLPgtwfEjNzZ4tnCa^{`GM&1=AyRmP1PA|CM&0K*(rj%xXDpgZeF~1s zZJn0b`0Ca{quDN#`8bN6CzmXlx#pR@em z`%b<%`~1r3-o@%qd#2?qRy442X4uBh5bI02m7Zw#s=%lKKraL6e?Z0UHZHl^NgsQ==mfosF%U$A~ zR-#&_Y4#@yIk#QZe{za7uu1BQAtUF7UByNb-_!!vGB@4%DIuG>%;xtYv$_4}lmeGuw3(%* z_|W70UimL8j!e)NpHRD@LXPXVx7+miK>gMpvsv!aXF(?O?!CBl|CLV3tajBkxvYyn z&V9xaearQAr0|WEkvpu^ue_SUGc7eD1hmre%wk^KSEe)E4^Og6r+k^B_9~S#Vv$5_z4u%LSuNf)r+u#T zb{;65sj#q*)AU;%&(}T~O?o$5Ex1?_dqu!G~)_r}PJ2TS_&NKzwVPq_|Ydg*H*+HCX!Ld&TnFjoAOr=YF zYm;BkIAEo^D*|vc(GY+LEp(^Eq^~$95H**DtGcpiCsb(&zByd zo3a7{2YSxc1nBRdTz%wD#>{S8mbU2hbygmthZnDXoj3WarlR`Uo^xjuoq8|zoqT$F zx+ExltbZbPx4|xoo9CH;#0$531zxg;bKN+jV>eAqw0E1*_$oeX&IgMNr#D2L$n9zP z(wjGFncp?Jw`T&kceM0g6W)BTNJISG4J%cJ{{pXOOxV>~t8%Vx!eqUUw=-(~{+j9- z5ix_&Y?o=&G^3s-M-iq4fj2Misx|TCyCxvPCu{ZOY3Pqbm9t(8v0dO{-zU6lL#dBL zn$Tt&iIDVzVck3~)tyiHP83AnGP*D`$HZo(H1mQFGA|c@y)sW%a_-*+I=zd^ea!Oj zotZFk;z0)MUhcBz{8dXGPyU-U@k)(Uu0g-qGm;uHHU!W){yA9S%>~2^WtUl^R>Fd1zSWDEIYHX~`D3>WD|PbQMKDEq>^E*M{Hv zZ`ZWn-fmIJIVGIeGCo%uv>yn_HQ>KyAlvoZL4(sfDcyU*Ymo`HOU}$Xz;^hB>~oiL z2RCc^EB#V8?rJW+%3kWka4kYE*3MzCh^f_Y$G>+v-+x(sv5zzJq3tfl+AZHC-Y6Pe zk~*`ck3T@t^1^cSz{CAV%5+vFiZ856T`+B{q2Oc78=IzG+^xCd_6BCtDelszuW$z6 z$hnkJ5oF)nXI8jEoN0liKz4TaBwm(Kg$th$_cot;8NA%juz_z&!_=D! zRTjtZzj$*zP>>vv=IVX=a6?LlLF?y$xr_(J+qUd@J7_z|8nELngWY5A2;{c?%9(r3P@Bc8cg}# zsBpgI&D^S%hwv_P=M5{3D>17~1rkqj*i8Oszw3PB-2RKUTvyKCSZsd$^0I|IMx~%i z+`43OqSxImT(4>xd{ol^A9pa-zc9V1QR?>#cV_;Sea*Ztdfxdi$>U;tt1LBl;qtn> z{HL@RYkRH`Uw8QDr?em|wHr=T?(}i)y}d$b@m&62A@3ImKE0UgbcHuNU`CUa;$mKb zSM9Gem|GH$Fy|PnHD}hJ1VxgREN|mPX{HUe+=n*?KL?*Q(kr=rK_92blpB%4LBZ@f zl45(=rWsf%Y}k5#vGS=ar*ACgO}!;DY4LB774qvACwk4^Vs+v4`V~)CPu#LUWlNzo zxOA>?POx~#tSEBpK_91wVBa~;HOWrz1owZr*K=-1{r`XeH)NJxcp-KoA7tX&nx1vb zm-{+Pro75Obl)D+)ozK{R8ss!`ZH`1}!+-6T; z-^%FrTKiS|+l*S*zXnUwB@Zw~Wij6V%(#lf;qt8o9!uR=4;pYuxVcYRIiJHJ(dv#> z>79+YC38$$!LvFi_HLbXX@Z>Z>cy;LTb&uM_i(OpWZT4lgiW@>>D9kU7gZw`zbrLj zaVz6Ekml(2{aS#&Y{Ma;5V_`GtXufPKM3grIQH#(C{y`_E1K2u-HNLor}Q=m?z$LQ z_3GHKf^3auEBOTiRyBWRnK}4V*g>15zk08Dxam*VEXC#+wL>>R!Jl!s%!FlyB-4U# zmtHXNf4zLgK}ObkMloAPKS#|>F;>1-U$+Z;n47Y*CR|`Ua?y|T-woE*^PpB?dT4~A zU5r)fhI7Xq#IqJpRnARn5Sz}=cYT@S%HQ4&4;fbPcVj=|X3YbxCY5bj9Om*T>6;%B z5BqYfhi@LE;x2~_NZS^Ue5RUVnqWZCx&e?87BKyN;54eXx*BeX~})a>7~b~jO8q* zj}m)RF0l43p4qfZks(^kBIeN4xXtowU*|o(8x9)N-7R9e>raB*V8gv-t=E<2r=chSW9)-?%E#fG*27=Ko8Nj94G@1-cyV&$)k zGjkQ38YV>wMCH4sOP)|MoMWY`oY+#QU@d=mZ?OBhH|(Zgdd}5d&E!J{v_QgoH=u6UFbA$|(7k{2=Hf$d|3Qw(tHQxN0bQH{R%0j684SL2;(Vo4vPm3I|wnWH(<- z%2YcYaKfi~XRy((mvgphW~lUB=s#D-vtR4)#l`MCMMXu6bEhVXF)jY>?KatDry@hv z@t(MOp0mFgU-{k`@c2bcjiPmg`QptyS0ANpDDg_*eR8q4`ij5j;lg^RUu#$l=kiCL znZa{>gRD>L&Bw?4C6$zw-J`R4wrGm8UDj+~e0qo5WJ^OugDS~~8CC~HnND~wE67z~ zU#Y0d(taqdWZJ_iDlhJ8GMYYeDC^6!TJEcyToNh$tw8qfZ^IqlYcD#7FkEW{WrTd|%_X+V5n+o!JI6 zE*&a}sWP?tZD^$R4P;DrdRCr;{E90UyY{DSX|$JOy28(xCF^4tP}pp9cw_l1!M5Ma z<&5vx|Ls^%-0^lsK(eIRR(ACWw-=E;^p(a zMXJ2;R8VyATF$a0`O6j7TT5haEUPm%-kdns6+Cu8y+x9Rb{*EFv1G%noHlWoG<({><(S5W(M*~t>rCS{Stauq6Vkohj1^xhGDtm?$?HwdnSEm7(GxSTDww5goM|g^ z?L7b0J;uBKbZs*<-{sCIv~RKOCRtGOQ#AK*`4@@c zKM%b#)Z~{)n-#R#M6f0Ix4q9`wVmReu;M-QLf0FQU(J}1EWXuzv2oqsUtj-cOjDL& zT9Rkw{%(rGW_N4V9fze%cAMOp7B{iDMQ`7gj`hk;8Iym5(*LxQ1y92jq}Qxn>)stA z)xwZdxop|8XBj_&6j=(c2HvnzTg>P;S71loUn}Mnyara>zOzM4quef-Ef2D;aZh*X z=+H0HlRjeV%9qX3r+43px8lZ|O9iW6T(IU@`#R5f%i8_U+srqXW;m1y6u`ORd5ej_QCq_N_Np z7#YJ!aE zG4o)i(d@rkYC4=dFhX?D+Eq=W$KkIh9(U+Wi za&c{xoNaDSM$5++JRH+1q+WHFYn+*KAvyo7Ly!7{+X8-h$6Kz<6#BwUN@{%Pb~IZ5GXle z_REbm+-8@|grtt0_-(l1?nB43ew^F(${)@x%iQo(`@$#f3A5e4*Ih76b4Wdw5hWMt zYx2a8^ThKFKit=Cclc`hVv5(7UD*cbr#0MR`*b)UCe|<{NWoOo8_5<*+BKP|BimMYi`onSNIwm@5D2`@;Q7n`z}9h%;GRtFe%;9Aq%>^Q*zGc+!bO93v8IB3e=t_ zvLO>pwb=sj1*^Zym!mOox$Vbc=7e9^vj{A-4! z?X4P_7Xk`flZ|%mPkC@zXX)u?w(NDz?+Xs3xp0)aBy3jy?r)!T!~ClTv+4BwiMu6h zkCZti%s%HhowrZy{T5!vFRFP@bnZ*7F;-o?Szg)rd(XWZyQr)_P)##o_kNZwYYI%h zxH&h>Qgq01XGv4n+^pVm$Map<7s1<%jiz1h{vHczpEu7C^l@UfJi&7zhqK5%Wr4No z4?Wo>?ia0geNTR%WpLpWcmPal$}vTQU5vFRoxEEG9M+w7$U9zE&*>p^+wlA1<%NOf z+uRS;DztoSRd_GyIPdF%XK_MB>9gHZ*jcX3U}e4W;%L|w{aczhbIh+;scwm>GTrq( z`Gbjb!s+#Hv)i`tH(um@@x?oJ@pRiuW@{$CHjapBKH~O$`USH)?uT-O*CaE(3VAU5 zro*(w-#DY5lzelGVQ0Cbz?S-BV$sb94rY@w3U}Q|csb=l@k`Nd7BX}HO6-_o3rfMS zO~KiCt-yh><&9^KT{Co?uP8a!@Sr^Rf(@*#f|k-t+LO54-*sHL{dd6zwNm3>9j_Wd z<1+D+THbD4czmvW^TJ>wtKWu2QYxV28{OA)E~MY=n|l(6z^dyGiAFN~g_6E+ukbTg z-4%CwmG(vOI-}&>62JLxcxQc+Inlo@DK2BI^lW|p3a_(P=NZutE7ni>jz7HE55)frtqVrg)Q+D#iidPb!)*QdL z(tSnMclLEIoL=o4a`}#I+3N1Xo>FqzvevsW$#1XJskxJ$2d|Y(nAv@Av*O}vdp5JD zJ$m~W#sBEfb6B1qCC{7xtJQpOp0oVj_(KfqR=Z!a6UbRPW0p9-&?(g=XDoPs^PPCH ztoT>CUE8l&xj|`O4hy^QaW1^pbK=FxaGqu^@a|7maOdW*0t?60LIwRkP_g>zNehEU zuHbIT+K6%oH+|_P`D{|>=Gw-vnlT?{?r~Ul^)G1M7jwKK*fBCaa@^Lp7^HX^f3+Sc zxEF6E^u3WM<%7aTer>Lsb3#G;fq>ibMwh-fUNAOo zyu@bs&{oGD}D6!{+w_?`ZD4y70I|#^T=| zJntLN*@IG-I5TLK+u8RI<(Lj{b@a)o=gi5p(WrCp=ak#Ga?Xs@{KM;*je?{PGtcaC zzjaAFCNWlaNtdE)-g1_oI^_ZFEJxZ!uPuJ)`~Qj^DCs-e%yCXAIhJWsd)bJE?Xc0h zi?s@0d>qa?aqHh|XIOJMJuS^l z>W)ea!#+RGU4}1MO>!y~ePloRaIU#*bW2mxx6j#@#cg^*@3Myv<(L+1sx_IL+@I?8 zZTf@VYzZau9JR%w3(vkdyo{MCtD{lqZNUEKBn{DB3l0^V>{%(Ce8WohhL79)LM4-6 zqg$E_ZR$X6YqK_Y(Awe*L8isVwM$xGz4$k2;Z%OkT(|T;zrMcyzc6k~gH-B*o;531 zT1I(Y(qu_c{{IL=WZfoYyIZRsIWD>4Gh>kLE|%w* zW`5PNAirNiOm@P>z=~hxc5a7j5)RFgdT4h`Q_=37+w}O0`z@Q+E|SU>yJW`V_Fd_M zeQR%Cm)wjP-d7n1tfWtT)%>KxxhA=3-~6I2cb((rJiG;7Qg(fPd^&?_$3+*%{XI6j z?&KzL`4*+wdlYJ}oGUcp=3(3Wz4Pi!4Kih~NXW%ER4-)zQuJT z&rN=ltUy3>PRV7b8LDfx9 z8^cFM1FOgG_pdOmTAc9K-N|fnk(78wIGwyN#-i+@5MGK=%wV`wM?{fSt^l&1)9NZn-G1AdTa|G-lqES@NBycQ`!k-6L6h zqQs%?P|%cz5iSR&?djFqD>dVW?7LnjCuL{mi<+PnJsVVSzIgL3Be{4<3qy`e#g@klN@4MDeztWMY`(#LVtrru|4*Frj6HdI$`((L-;msU z3Y-jIh%#-t#qRXJk29x0E=9kCcUGdrncv*cym7yt%=fAv7bj0=GwVK_X79H8a3g2q z#hd)M+O4-SmH+fYdX+U$yeL@rCuvJP-6uWCQ=!tlhBc8jgk3LDQbG9>G8Nu09Rb!K2-VDNPHb6Mw< G&;$VI_y#cm literal 0 HcmV?d00001