From 6b63ef50f95662b7e64e787797116c5973cd063d Mon Sep 17 00:00:00 2001 From: Chris Danford Date: Sun, 25 May 2003 20:19:01 +0000 Subject: [PATCH] support theme-specific program icon and window title (useful for non-SM products) --- .../default/Graphics/Common window icon.png | Bin 0 -> 967 bytes stepmania/Themes/default/metrics.ini | 1 + stepmania/src/RageDisplay.h | 4 +- stepmania/src/RageDisplay_D3D.cpp | 39 ++++++++++------ stepmania/src/RageDisplay_OGL.cpp | 8 ++-- stepmania/src/StepMania.cpp | 42 +++--------------- .../arch/LoadingWindow/LoadingWindow_SDL.cpp | 28 +++++++++--- .../src/arch/LowLevelWindow/LowLevelWindow.h | 2 +- .../LowLevelWindow/LowLevelWindow_SDL.cpp | 29 ++++++++++-- .../arch/LowLevelWindow/LowLevelWindow_SDL.h | 2 +- stepmania/src/splash.bmp | Bin 10244 -> 0 bytes 11 files changed, 89 insertions(+), 66 deletions(-) create mode 100644 stepmania/Themes/default/Graphics/Common window icon.png delete mode 100644 stepmania/src/splash.bmp diff --git a/stepmania/Themes/default/Graphics/Common window icon.png b/stepmania/Themes/default/Graphics/Common window icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6fe4bc9e8ef61ee0fd83543593d7e4d543e8ce4c GIT binary patch literal 967 zcmW+#e@q(%6n@t$y@Qr|r5hAH@EF5YetAoD&~;?jpFjo!Dk20EuLZ#+QwWtxki~TYW>kY{+;S^a&wzmlvav+nI%XVMHvX6k+f3@=AMbt1OTL%yd-+~p z#nGbpxRf{mh%YHN+eD;x3YUr9+0pS(gxHqiS|@;9y;BJI$28(l+GHp*08INjpH_an z!>BK|l>u~Q0&s4C$59dQ0<_Tpn=HV=QGlf8;Wxro0JN~gY^Z9#;nDx>NhVTi z8(cWV!JdW4xW01#fg+wRE-Zd7$GrSY3{FkvVvnT_H^=ovsnA-1^ONqYT1b2KZy(@P zB**(CrBN3|TXd2Jo#60X948bFZW477!x$+2qoA9D66z@WyzkcxOWndc^Bhofvz#4cMU#gO~^7sdhD?Y z6h{Y>`_m~emE4n!bf?0Kd#-gOh>VyRmqbcDitPG5pE)3e1Iv)yOYULM2EGuPbx4eh zf%!ZRLjFH*8G6P(3QQo`E`x_V;XAHdM3C99_kE9o1aCUyJ?&tRu*cA!69y`btyqpHH~%i6J7W5PEAUDyFBZ{4l|4d%=m}(5AVqa6C9)@KBlux zmZK6S^`ngc(szlvg|1X%sg`j{atxDtNwrd3XuzlJ@JdaM%|uopme1*L~VGi#wMC!h+;F0(hLzh(u*OiQ=k%rM5P zb^6eW=AIj+VuS{=H0!Eu5}oqhQX=8}peazRy8Oi2JoLXC-jZkgv}-9{xY{2f&L^m< zKL}uj3RFt0dGId_tncA@SYU77D9Tl$zj|#=>@l@yryAo^&R#c4KDo2CebRz1BXrwr z4rUiGyH1*1(wVpT5&e*f7XnD*xD$v`|`YBPB4nq&9P8j)$*gv=?*c77nRIAYpSU< gio0+hZ2K7w0sD2$ou95uOp8wkC6=S+uZ(Q>e*m#j$N&HU literal 0 HcmV?d00001 diff --git a/stepmania/Themes/default/metrics.ini b/stepmania/Themes/default/metrics.ini index c408fd832a..d8f3f600a8 100644 --- a/stepmania/Themes/default/metrics.ini +++ b/stepmania/Themes/default/metrics.ini @@ -17,6 +17,7 @@ ColorP1=0.4,1.0,0.8,1 // sea green ColorP2=1.0,0.5,0.2,1 // orange InitialScreen=ScreenCompany +WindowTitle=StepMania [Notes] DefaultScrollDirection=0 diff --git a/stepmania/src/RageDisplay.h b/stepmania/src/RageDisplay.h index 64638062ee..c308807103 100644 --- a/stepmania/src/RageDisplay.h +++ b/stepmania/src/RageDisplay.h @@ -69,13 +69,13 @@ class RageDisplay friend class RageTexture; public: - RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync ); + RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); ~RageDisplay(); void Update(float fDeltaTime); bool IsSoftwareRenderer(); - bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ); + bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); /* Call this when the resolution has been changed externally: */ void ResolutionChanged(); diff --git a/stepmania/src/RageDisplay_D3D.cpp b/stepmania/src/RageDisplay_D3D.cpp index 3e2771a09d..cd800b8ffe 100644 --- a/stepmania/src/RageDisplay_D3D.cpp +++ b/stepmania/src/RageDisplay_D3D.cpp @@ -28,6 +28,8 @@ #include "SDL_video.h" // for SDL_Surface #include "SDL_utils.h" #include "Dxerr8.h" +#include "SDL_image.h" // for setting icon +#include "SDL_rotozoom.h" // for setting icon #include "arch/arch.h" @@ -166,7 +168,7 @@ const PixelFormatDesc PIXEL_FORMAT_DESC[NUM_PIX_FORMATS] = { }; -RageDisplay::RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync ) +RageDisplay::RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) { LOG->Trace( "RageDisplay::RageDisplay()" ); @@ -242,7 +244,7 @@ RageDisplay::RageDisplay( bool windowed, int width, int height, int bpp, int rat } - SetVideoMode( windowed, width, height, bpp, rate, vsync ); + SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ); } void RageDisplay::Update(float fDeltaTime) @@ -350,17 +352,29 @@ HWND GetHwnd() } #endif -bool IsWin98() -{ - OSVERSIONINFO version; - version.dwOSVersionInfoSize=sizeof(version); - GetVersionEx(&version); - return version.dwMajorVersion == 4; -} /* Set the video mode. */ -bool RageDisplay::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ) +bool RageDisplay::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) { + /* Set SDL window title and icon -before- creating the window */ + SDL_WM_SetCaption(sWindowTitle, ""); + + SDL_Surface *srf = IMG_Load(sIconFile); + SDL_SetColorKey( srf, SDL_SRCCOLORKEY, SDL_MapRGB(srf->format, 0xFF, 0, 0xFF)); + + /* Windows icons are 32x32 and SDL can't resize them for us, which + * causes mask corruption. (Actually, the above icon *is* 32x32; + * this is here just in case it changes.) */ + ConvertSDLSurface(srf, srf->w, srf->h, + 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + zoomSurface(srf, 32, 32); + + SDL_SetAlpha( srf, SDL_SRCALPHA, SDL_ALPHA_OPAQUE ); + SDL_WM_SetIcon(srf, NULL /* derive from alpha */); + SDL_FreeSurface(srf); + + + // HACK: On Windows 98, we can't call SDL_SetVideoMode while D3D is full screen. // It will result in "SDL_SetVideoMode failed: DirectDraw2::CreateSurface(PRIMARY): // Not in exclusive access mode". So, we'll Reset the D3D device, then resize the @@ -486,7 +500,7 @@ int RageDisplay::GetMaxTextureSize() const void RageDisplay::BeginFrame() { if( g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET ) - SetVideoMode( g_Windowed, g_CurrentWidth, g_CurrentHeight, g_CurrentBPP, 0, 0 ); + SetVideoMode( g_Windowed, g_CurrentWidth, g_CurrentHeight, g_CurrentBPP, 0, 0, "", "" ); // FIXME: preserve prefs g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0x00000000 ); @@ -907,7 +921,6 @@ void RageDisplay::SetAlphaTest( bool b ) g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER ); } - RageMatrix RageDisplay::GetOrthoMatrix( float l, float r, float b, float t, float zn, float zf ) { // D3DXMatrixOrthoOffCenterRH @@ -917,4 +930,4 @@ RageMatrix RageDisplay::GetOrthoMatrix( float l, float r, float b, float t, floa 0, 0, 1/(zn-zf), 0, (l+r)/(l-r), (t+b)/(b-t), zn/(zn-zf), 1 ); return m; -} \ No newline at end of file +} diff --git a/stepmania/src/RageDisplay_OGL.cpp b/stepmania/src/RageDisplay_OGL.cpp index a76e60363c..deca127d99 100644 --- a/stepmania/src/RageDisplay_OGL.cpp +++ b/stepmania/src/RageDisplay_OGL.cpp @@ -106,13 +106,13 @@ void GetGLExtensions(set &ext) ext.insert(lst[i]); } -RageDisplay::RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync ) +RageDisplay::RageDisplay( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) { LOG->Trace( "RageDisplay::RageDisplay()" ); wind = MakeLowLevelWindow(); - SetVideoMode( windowed, width, height, bpp, rate, vsync ); + SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ); // Log driver details LOG->Info("OGL Vendor: %s", glGetString(GL_VENDOR)); @@ -258,10 +258,10 @@ void RageDisplay::ResolutionChanged() /* Set the video mode. In some cases, changing the video mode will reset * the rendering context; returns true if we need to reload textures. */ -bool RageDisplay::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ) +bool RageDisplay::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) { // LOG->Trace( "RageDisplay::SetVideoMode( %d, %d, %d, %d, %d, %d )", windowed, width, height, bpp, rate, vsync ); - bool NewOpenGLContext = wind->SetVideoMode( windowed, width, height, bpp, rate, vsync ); + bool NewOpenGLContext = wind->SetVideoMode( windowed, width, height, bpp, rate, vsync, sWindowTitle, sIconFile ); if(NewOpenGLContext) { diff --git a/stepmania/src/StepMania.cpp b/stepmania/src/StepMania.cpp index 1c22cef60c..0a61e0929a 100644 --- a/stepmania/src/StepMania.cpp +++ b/stepmania/src/StepMania.cpp @@ -95,8 +95,9 @@ void ApplyGraphicOptions() PREFSMAN->m_iDisplayHeight, PREFSMAN->m_iDisplayColorDepth, PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync ); - + PREFSMAN->m_bVsync, + THEME->GetMetric("Common","WindowTitle"), + THEME->GetPathToG("Common window icon") ); bNeedReload |= TEXTUREMAN->SetPrefs( PREFSMAN->m_iTextureColorDepth, PREFSMAN->m_bDelayedTextureDelete, @@ -145,30 +146,6 @@ void ResetGame() } static void GameLoop(); -#include "SDL_utils.h" -#include "SDL_image.h" -#include "SDL_rotozoom.h" -#include "StepMania.xpm" /* icon */ - -static void SetIcon() -{ - if(!SDL_WasInit(SDL_INIT_VIDEO)) - return; - - SDL_Surface *srf = IMG_ReadXPMFromArray(icon); - SDL_SetColorKey( srf, SDL_SRCCOLORKEY, SDL_MapRGB(srf->format, 0xFF, 0, 0xFF)); - - /* Windows icons are 32x32 and SDL can't resize them for us, which - * causes mask corruption. (Actually, the above icon *is* 32x32; - * this is here just in case it changes.) */ - ConvertSDLSurface(srf, srf->w, srf->h, - 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); - zoomSurface(srf, 32, 32); - - SDL_SetAlpha( srf, SDL_SRCALPHA, SDL_ALPHA_OPAQUE ); - SDL_WM_SetIcon(srf, NULL /* derive from alpha */); - SDL_FreeSurface(srf); -} static bool ChangeAppPri() { @@ -259,11 +236,6 @@ int main(int argc, char* argv[]) LoadingWindow *loading_window = MakeLoadingWindow(); - /* We might be using SDL, so set generic window properties (icon and caption). - * Be careful; we might not have an SDL window at all. */ - SDL_WM_SetCaption("StepMania", "StepMania"); - SetIcon(); - loading_window->Paint(); // changed to use time. GetTimeSinceStart is silly because it always return 0! -Chris @@ -299,7 +271,9 @@ int main(int argc, char* argv[]) PREFSMAN->m_iDisplayHeight, PREFSMAN->m_iDisplayColorDepth, PREFSMAN->m_iRefreshRate, - PREFSMAN->m_bVsync ); + PREFSMAN->m_bVsync, + THEME->GetMetric("Common","WindowTitle"), + THEME->GetPathToG("Common window icon") ); TEXTUREMAN = new RageTextureManager(); TEXTUREMAN->SetPrefs( PREFSMAN->m_iTextureColorDepth, @@ -310,10 +284,6 @@ int main(int argc, char* argv[]) SDL_EventState(SDL_QUIT, SDL_ENABLE); SDL_EventState(SDL_ACTIVEEVENT, SDL_ENABLE); - /* We might have a new window, so let's make sure window properties are still set. */ - SDL_WM_SetCaption("StepMania", "StepMania"); - SetIcon(); - /* Grab the window manager specific information */ SDL_SysWMinfo info; SDL_VERSION(&info.version); diff --git a/stepmania/src/arch/LoadingWindow/LoadingWindow_SDL.cpp b/stepmania/src/arch/LoadingWindow/LoadingWindow_SDL.cpp index 1a111aef1d..f230561c66 100644 --- a/stepmania/src/arch/LoadingWindow/LoadingWindow_SDL.cpp +++ b/stepmania/src/arch/LoadingWindow/LoadingWindow_SDL.cpp @@ -2,8 +2,10 @@ #include "SDL_utils.h" #include "SDL_image.h" +#include "SDL_rotozoom.h" #include "LoadingWindow_SDL.h" #include "loading.xpm" +#include "StepMania.xpm" /* icon */ LoadingWindow_SDL::LoadingWindow_SDL() { @@ -11,23 +13,37 @@ LoadingWindow_SDL::LoadingWindow_SDL() if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) RageException::Throw( "Couldn't initialize SDL: %s\n", SDL_GetError() ); - /* Load the BMP file into a surface */ + /* Set window title and icon */ + SDL_WM_SetCaption("StepMania", "StepMania"); + + SDL_Surface *srf = IMG_ReadXPMFromArray(icon); + SDL_SetColorKey( srf, SDL_SRCCOLORKEY, SDL_MapRGB(srf->format, 0xFF, 0, 0xFF)); + + /* Windows icons are 32x32 and SDL can't resize them for us, which + * causes mask corruption. (Actually, the above icon *is* 32x32; + * this is here just in case it changes.) */ + ConvertSDLSurface(srf, srf->w, srf->h, + 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + zoomSurface(srf, 32, 32); + + SDL_SetAlpha( srf, SDL_SRCALPHA, SDL_ALPHA_OPAQUE ); + SDL_WM_SetIcon(srf, NULL /* derive from alpha */); + SDL_FreeSurface(srf); + + + /* Load the BMP - we need it's dimensions */ SDL_Surface *image = IMG_ReadXPMFromArray(loading); if( image == NULL ) RageException::Throw("Couldn't load loading.bmp: %s\n",SDL_GetError()); - /* Initialize the display in a 640x480 16-bit mode */ + /* Initialize the window */ loading_screen = SDL_SetVideoMode(image->w, image->h, 16, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_NOFRAME); if( loading_screen == NULL ) RageException::Throw( "Couldn't initialize loading window: %s\n", SDL_GetError() ); - /* Blit onto the screen surface */ SDL_BlitSurface(image, NULL, loading_screen, NULL); - /* Free the allocated BMP surface */ SDL_FreeSurface(image); - - } LoadingWindow_SDL::~LoadingWindow_SDL() diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h b/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h index 0671d23e68..e594cea3e4 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow.h @@ -13,7 +13,7 @@ public: /* Set the video mode as close to the requested settings as possible. They're * hints only; it's better to get the wrong mode than to bail out. */ - virtual bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ) = 0; + virtual bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) = 0; virtual void SwapBuffers() = 0; virtual void Update(float fDeltaTime) { } diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp index 7ae38ac350..9caf38264e 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.cpp @@ -1,6 +1,7 @@ #include "global.h" #include "LowLevelWindow_SDL.h" - +#include "SDL_image.h" // for setting icon +#include "SDL_rotozoom.h" // for setting icon #include "RageLog.h" #include "RageDisplay.h" // for REFRESH_DEFAULT @@ -23,7 +24,7 @@ void *LowLevelWindow_SDL::GetProcAddress(CString s) return SDL_GL_GetProcAddress(s); } -bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ) +bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ) { SDL_QuitSubSystem(SDL_INIT_VIDEO); @@ -40,6 +41,26 @@ bool LowLevelWindow_SDL::SetVideoMode( bool windowed, int width, int height, int SDL_InitSubSystem(SDL_INIT_VIDEO); + + /* Set SDL window title and icon -before- creating the window */ + SDL_WM_SetCaption(sWindowTitle, ""); + + SDL_Surface *srf = IMG_Load(sIconFile); + SDL_SetColorKey( srf, SDL_SRCCOLORKEY, SDL_MapRGB(srf->format, 0xFF, 0, 0xFF)); + + /* Windows icons are 32x32 and SDL can't resize them for us, which + * causes mask corruption. (Actually, the above icon *is* 32x32; + * this is here just in case it changes.) */ + ConvertSDLSurface(srf, srf->w, srf->h, + 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); + zoomSurface(srf, 32, 32); + + SDL_SetAlpha( srf, SDL_SRCALPHA, SDL_ALPHA_OPAQUE ); + SDL_WM_SetIcon(srf, NULL /* derive from alpha */); + SDL_FreeSurface(srf); + + + Windowed = false; int flags = SDL_RESIZABLE | SDL_OPENGL; // | SDL_DOUBLEBUF; // no need for DirectDraw to be double-buffered @@ -152,7 +173,9 @@ void LowLevelWindow_SDL::Update(float fDeltaTime) DISPLAY->GetHeight(), DISPLAY->GetBPP(), 0, - 0 ); + 0, + "", + "" ); // FIXME: preserve prefs } break; } diff --git a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h index 45e2c10e04..8d71f56aa5 100644 --- a/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h +++ b/stepmania/src/arch/LowLevelWindow/LowLevelWindow_SDL.h @@ -12,7 +12,7 @@ public: LowLevelWindow_SDL(); ~LowLevelWindow_SDL(); void *GetProcAddress(CString s); - bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync ); + bool SetVideoMode( bool windowed, int width, int height, int bpp, int rate, bool vsync, CString sWindowTitle, CString sIconFile ); void SwapBuffers(); void Update(float fDeltaTime); diff --git a/stepmania/src/splash.bmp b/stepmania/src/splash.bmp deleted file mode 100644 index ce387761b1fc2f3684e31c539da7c8cfea549285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmbta=~tWCd4Jw(N$j%3A|WKdGq#a1SeWrDgOlK4GuDETKtcipLV#_wF9@*>NF&>m zc+xb@+N4REPSR=8PMfxqG&wnwbCT|#+Mb?%?1%mVJ>C9+^!L0H6YykCKh%I<-S^)6 z+~0lfvtNyQR98s(_ec=&$1TVYF-qtIe=m8J{$l?I9nW8;lJ_F@ zb~n?PHwNg%avxR0R{BMCgx&-FAMD?yzb;$pr+b$%&q{xo?V}$a4AOhsgH-Zeq`6@u zeLa4a5)Wm1H$Oz5i(R4B*Uj|cdMDlM*VB*7H)!Z$8~xzu8ogh!(RX%jBwAD?z=W=1 zhPwXjed>DWJ0x0LsrlVMrKTVK6={F|kJS3j?@@F4ZEF4OZ&TySBhr51TcrQPpHSzw z-y`GuzaZ03|DL*j=l7}WE8nKB-~2jV_{)DH(|3MAU2lJhx}JZY%-{bJbrue&=ZoJY z3&vgkv!BtxKm03M-u^O~4xUo~-~J03Q`=;Cl%xyAL+btPm+9&^-le-g`Z?J@{dv0c z&U-Za!QaujuYI2yk~^ev&5>s47G3z}ACcuN@6ZLTX?gZ}>IV+n_kKiu@B9f}`Qo?8 zR{bp9e(xt_JE+p@fAh~|jpykOFk0L`>Wx04q5M8M-h4rt-}(-jzx_ipE=1|p+h3)Y zd*d|zwLc)$t2TP&3*V=E#WzWGSxB7kq&EC@_q<9%)uzY^iJ$(0R6QnB4+Ka2l;~WK zPR~N5eD2V*TzPU_slL^KagHkvW!%?@w69n94$5!7`Q~nUEuBuQ zr$|3PH}}w+FYH&UFN6>+{U&AXZxc0C_KSs$@|&dEB};j2Ej^E)srmW&xmj;0mvcR+ zibnH@wF%ln;>$#x)d~bW?l(13kv ztR9z+S65e7)KS$k=|EvAm46Bnxm+%h2&r7u4FHpq?p5)ML)Km$HaCj6+vkdFUguqa zLet(p2!O&0siM?b+edndf#f!`pp!^6x~S6`sEA7rd%HYrZxz+B&$qp$aQ$tP_N0B) zDz)IaR_cr(Rhl$QsZ>4`)8y!tM8XBW`(6IPBpBfsHfk-yIJWS_c*L^`yUIvjkW`UM z4Xf1f1Z2QWQm3hDerYL{jKy*}Qf2AYoIm06y8`~~_5&fT{lkOcNR7_8&li26;Q0)Z zI=)|;2B8&FD}uminwRF6QVaPcNU1?7aO4m81KDtRN{F@rhf!;=w+nH9Vj?r{TMX7H zeHxlk-78H`msUx=LR~=!2cI#NV{R^$T1bWxz@^S=0%Qt@-w>jGz%Fa;BTUFQp7Bgf zET-R5_6ADLm3s$Qnvsb!#>Tbi9^a<0&Q zKZu3HZv2Ed(}m4vLKqDyne=vp5H4(%$+;u$;~Ku_M5?_~sf2S-v6e#CE%p7*fuh%& zoC!_d_vgSt_qcogQyMtuOIFLEEX#bb2`~@@Jx;eLTlr5RbxPNpd!_4ACu4m^q#&>3ulvdwH4V%q2Nfu`H(b~?vA(~SBSP~T;`Pg(LyPhgY|NnL;*YFOl# zmejM<3dA#PMYEf$ariHDiw^2z9CSeTLEmT|hIsiDylzrCNfmHrEB`H|yVA`DS-M@P zu8ki&S&725Z)}tcg#x&(VqU9fRbFaf>N8K`1nQQQL$6#b8o?tu2KI_=BHP_iI9G{rT+`zdUdn4y)XE~A zbcGfkKF$U~*<_L}vH_9@x*&`X{5vRXTX@~`)7z18Cq#eLf8-2r#Oc3qo><{V9e)>8 z8cI_vtnISnWA~LzrAW0v?Mbf-vgpcJg&1r%n+>u}BTIH@O*8L6mMz-$7ObF+&qmyV zQDumKk%7`kiC0$-r9NDtaI{z;?Ixw8+v$wc!6%kZNg2t^D5zT;O4?=kDpAT7Mni z?RYe}!e%^O$mhY^?d_VY4MD?aX0iYo7ace>gKRPO@!=`p2pqQXS=#OP!2vysN#)2h zmUTJD{I1Dd@I|kXZi1V@BHaR)u)cH?Pi`wuZa2%)HE#10Xjx)Ew*O>Y9rgK2@ktFe z!UMQ=Qg746EF5zPwj(h)7DywavEc_0EebQ4uL^1~*5Z(d9fRfp8LWNc2_#&BNtb`p zpQ{4(b!hy}7R3@`&Ffm3&fV<2Nx*m=n3Z02uXM8!ZSLpMCvEP>xYzhSKe4B7?CJj; zcQU@dH&vymSo21NKD@bY)jFxRx3gJwf|@4B5M&7J;2`!Q*(FP(Olp=EWp5^fV%`xo zBBI%L`<+KFmn-S@AHPMHAq^}W9eB3N)Nrj6Cb07sVIRG~t@J?~ZUb*G@SJJa`fG2S z#K(-dgB{<%m^07Xju6EZG|Myu@1*Q!d;QU)^>u8>pYSI}$DSepx?-?funiqN2+NnE z1$Qsyy z)=A&V6JvT`9>aTR>Q(H)nP>fU8umEDNW)&H$%4QV=Y#EFKkJAC5Y8pwu=G%4wn3NA zs59@&ChH7WO?~o+S=r2(-%sipI_J$z^9glh7q_t+e%`8KBXu_ps++h6Z?1#;-9WF5 zthG;%INS5`NU8fo!uAU3LPMHd2(?17ZERo%TgZe10p~iT%O(%kj)0Hh)|jW*qIrG47m(#5J_v=7tsITQrfi^YAWROk9k3KRZaIaTrQ8Bd z+*;2hHgoHlaCRLD4s#h`QxBFZmz7AM^K?AGp7=U@}VFw8gUSC z&L6*EuD%9&ybd{5p1{Dqh@+f~`n%GQbfexn(~G?*ZHzke{^fQZd*k!+5=3HiQ?*UT zBTnP*-_PyBV2evO1g9J+SlH7WH8Pzy%0@#w;%l(i6F3Tx#!tGOpKAy)uosn@`Qme+ zRLgix5G#Ge8YM zn80ap6ts|Hgz0Kc&wvkFQ}f-XQy#qb23$lhc=q9#)1R4lz+x$-<`ioSa|_>%L^U_f zsTm?e9Skd71M^rk?WklpWQ*Bs6(a9;W|b-jsvQ6p3W0M9u8lZw-GLrogcd1JocB%W z{|!_92?S@}1EbPDd7g}ad0ZW>`M5lXDhYhE;+zBF%{`oQi%y4RiNHBE(BiD|=|o6% zFu&%09Z<)dPSjISS4kkpRVS$lwX!*6>V*nR=|!Nv1JueBD6T;+*(!B54M}&AADpyL z^^=-|t&8l#*&CkfQD&ZLpWv@-%%v9K+!Xwo2)pG=CWFrExawffVCj&_s&m+EcAb1l z#QjGB7wR{_>`EdZT7X`qmQaD5O79`Az`8>pu>sd0=WM%vji#T@6@LAQI!d`(L=G9s zWf4JS;DSE|7CRiA63BfP*#awY&Th02o_*}y%vO^Sp9;GIF4U|b4nXQn!2kg2JYzjZ z-RojKAArQ3$qT?Y*0eKu!s#~pKQ^B@J&uv1M$ohJa1LHfLH?)=8{4CYBFTfs_Cd(R zISb-zM9BjPANpmRNhb?Y4LOg%UdXX)Cg}x-Arz?CrVHt*<$ZA;xRsb6xUYlX-St>n z$r-TznOxv>8@N9tQ!NPlem>0k|bE{?(*i-+i z@9ev?tvX^ko(HSFliSQ?aS1uP*=8~gTFj2&EB$89&FwGLqOE^q*kZHw_4UbivrWEg z2k7Gfv)ey83D6Meh1rFrxp_q08q{Nhr5Dh}5B)G_G&k>ne)o0k9X#cp>o|jpjVC_2 z-m3Sp7yQ^Uj2zW9^YRean+)^GClnn)JiRu;Rcy5 z*ew<-oW*L^iJ;i!eaK?sg&xj=)AL-pRWC=UN{XlJ20D)OJ1ww8wfG)+S16YTWShys=Gdm!4_`I3HNrcOY|VKV7m?13 zR-*&Qz?N^&VPxT+8lRj*32Wv7qG9IrY|VS5)5}Fv23B7n$~=kfdl5VE+Bfj*#EJ9s z!x+Eb{_uUBlZJR~EeZ=J+RSDP`w7RrVV&LtOx7)L#D~i3ga^{ms@2)e9O>AGVJn0P zj-j-TYG9IZQ=vm)m^~UWF{ogv_gB8RQ>itugkD2MIY zXlpSe>qK;A85p*<^SNHxD#S9r@o`UN+&8fU*ln_70KjFITK%gcI(i>+iTWyPb8`}E zjF8C&1{Dpiau%e-(_OfG>b!n~P+LMx705cJUR0d$8R+ntaRMJc;Vf@RcRo4-)sxq1 z=lV7QWt%*r1Sqn>pw!HUwq_Q6KA*=^`<=+(Tx}-11vqUexjSA#RG15adkDDa5U!wL z`750Jj8loDw-^KafSb$}6spI1OgNyccGOx?lIlYwEVlfMi#{9?FXb7}xZM-?Az&tx z#mpAd;9zClk8NWyh!58+=jj|Q3j`hoUU21@S5tH~0V~}gYeduCTAdkHduNM%WMo8k z4BL$60Sg?2h_6K!eUV6pcQ-LHG49E@$9*YuU_sOe+OOJ25KD@!R4zI5@By|4v6!F2 zf~bHuptP>6XjQx()>Hf&IDHGcRp%${e^-Zo(BT+>EZXiF^t#q&6oLYar1D7-wU6#% zpBb(Mk7saAg_6F_aSsj*m2ISs@ux>`xE?}7uqqZ^hA~>kk_W++=$^G6hhkkNdd0fz zwXQR75knb!92O%AXv229tiN}!rK91Kg296d)>L9pta&ArnbOtOcn{^hQ5y^sh{v?vY z?!aBr_{h#@%6mO>k3$9Z{pK!*xg86mn93`!#b$BGSl_BTs9upu5-N}^J;_s^fLD7H z_NUJ}&~Mh8Edyq~wH@3Nl{Y}!?P>O@JalW^jfFGwLR>K0t=6lkB{(d0g9YU(Y!M!n zW0o}YGl-fbYQC#0`_Hjfw{!!icO!{YM2yIKQ-8y&9um!U^mKG|*i1HywZF^maJ0Ab z%JDo{i(4>=E&r!{02W3QMxj8M+AoNXHvIsu0TAY!^$@D*&AB=T)OUio$Y%(vrM*6^ zi1@BMg>zL8Df+CmdHn;T^Cq*Q-E1(T;3&&hQy=F-n&&Iwh{vt=P$O2J;MKu_R)|#C z=Vx1J>cJ=(+BP7YY(_^H44x>)@+n+47x;jA|Eg7KUy9dPX?67L`f!S}Y%=xXHm4~* zz4-`NIGGI2QSzvKSgV=07iRJXShCIv`>sBR1I?qN_SzvW_dUYRC zQsZN@-a2SQJU`Ihf%}|}=?sh@wB8p1d}yR^!bjM{Yq)vIj88x#P3?Vf(@(>5yr9D_ z8_bOkyBS5*Xtre7g;C62nH)+b<>Jf699z@ygCVUMkmhu~gXc1*` zCVvdC3htCi>d?aH$G3g(RuPa?Ez%`^fRLn^nliSvD>y0U!~z^&C|SN<5p zj5-HLdh8j+!R~IE)Q6;rmT+Ir2PkmY-*^na<;(aYnnfDMd4ZVQJsO^d6vU_J!p_G| zZ!UCyHu03jU$#Q*?dE>ArMNJ!i1^;K;z~&YMgreBP#tF$BPt(g^|LjG-5(wI9Hq;# z@Tl|g|4m{>mf5+;lr z_{pOqB!yn&D-XP}B2e}?5Wzx_Ow7m*7^}+R;eo;_d}pF*nw5wJk<^QH3z$6ETmbci z$)o$Zr}%onjB9c>A48rR1g$|BSf>GClwLTewq9hf1eOEtcJoyfG6iNFCs5hFVp%nl=yM3Mtv4nAPE zVF|jNU)y-Lj}W6p5AloduP90<@a>yB@l*tJJ(#Ub=CUg89K8HB5yhhO?D9rBT_~6M zgjw45kCik1Cj9Vm7zH*I<}w*BU!f+1xeLVKXh|)>6fdnoXEyTrX!>yV6Tq*k9PBIh z@LSk*{DCv$39B;H6vk9!l#F;*vqYWgC0w0sY@|2vjUd$V#9nDn(UEVXj_uz&d zi(=0G`%j;`xUlztbGbEDf!c5Zd$@6kFP}sY_V<)idIvZw>21`kds-0xzQ;-Rt?67S-> zN!6{=?snGiKMEz`=GBPRq-ALtc+?QN`nc~a{}Mq^eZa#OYkM3Kf-z{uf(O&wu~`