diff --git a/Core/Core.cpp b/Core/Core.cpp index aa0104d58e..d5862b1785 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -130,22 +130,40 @@ bool Core_GetPowerSaving() { return powerSaving; } +#ifdef _WIN32 +static int ScreenDPI() { + HDC screenDC = GetDC(nullptr); + int dotsPerInch = GetDeviceCaps(screenDC, LOGPIXELSY); + ReleaseDC(nullptr, screenDC); + return dotsPerInch; +} +#endif + +static bool IsWindowSmall(int pixelWidth, int pixelHeight) { + // Can't take this from config as it will not be set if windows is maximized. + int w = (int)(pixelWidth * g_dpi_scale); + int h = (int)(pixelHeight * g_dpi_scale); + return g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); +} + // TODO: Feels like this belongs elsewhere. -bool UpdateScreenScale(int width, int height, bool smallWindow) { +bool UpdateScreenScale(int width, int height) { + bool smallWindow; #ifdef _WIN32 // Use legacy DPI handling, because we still compile as XP compatible we don't get the new SDK, unless // we do unholy tricks. - HDC screenDC = GetDC(nullptr); - double hPixelsPerInch = GetDeviceCaps(screenDC, LOGPIXELSY); - ReleaseDC(nullptr, screenDC); - g_dpi = hPixelsPerInch; + g_dpi = ScreenDPI(); g_dpi_scale = 96.0f / g_dpi; #else g_dpi = 96; g_dpi_scale = 1.0f; #endif - + smallWindow = IsWindowSmall(width, height); + if (smallWindow) { + g_dpi /= 2; + g_dpi_scale *= 2.0f; + } pixel_in_dps = 1.0f / g_dpi_scale; int new_dp_xres = width * g_dpi_scale; diff --git a/Core/Core.h b/Core/Core.h index d21ec4847a..889e05ccbe 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -47,7 +47,7 @@ bool Core_IsInactive(); void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); -bool UpdateScreenScale(int width, int height, bool smallWindow); +bool UpdateScreenScale(int width, int height); // Don't run the core when minimized etc. void Core_NotifyWindowHidden(bool hidden); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c00e0a02ab..3b90519980 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -273,7 +273,7 @@ void GameSettingsScreen::CreateViews() { static const char *quality[] = { "Low", "Medium", "High"}; PopupMultiChoice *beziersChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iSplineBezierQuality, gr->T("LowCurves", "Spline/Bezier curves quality"), quality, 0, ARRAY_SIZE(quality), gr->GetName(), screenManager())); beziersChoice->OnChoice.Add([=](EventParams &e) { - if (&g_Config.iSplineBezierQuality != 0) { + if (g_Config.iSplineBezierQuality != 0) { settingInfo_->Show(gr->T("LowCurves Tip", "This option will significantly improve/reduce the quality of rendered splines and bezier curves"), e.v); } return UI::EVENT_CONTINUE; diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 010f57ed79..19c78593e6 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -204,15 +204,6 @@ namespace MainWindow rcOuter.top = g_Config.iWindowY; } - static bool IsWindowSmall() { - // Can't take this from config as it will not be set if windows is maximized. - RECT rc; - GetWindowRect(hwndMain, &rc); - int width = (int)((rc.right - rc.left) * g_dpi_scale); - int height = (int)((rc.bottom - rc.top) * g_dpi_scale); - return g_Config.IsPortrait() ? (height < 480 + 80) : (width < 480 + 80); - } - void SetWindowSize(int zoom) { AssertCurrentThreadName("Main"); RECT rc, rcOuter; @@ -281,7 +272,7 @@ namespace MainWindow PSP_CoreParameter().pixelHeight = height; } - if (UpdateScreenScale(width, height, IsWindowSmall())) { + if (UpdateScreenScale(width, height)) { NativeMessageReceived("gpu resized", ""); } diff --git a/ext/native/gfx_es2/draw_text.cpp b/ext/native/gfx_es2/draw_text.cpp index bd85729c49..088a9c09af 100644 --- a/ext/native/gfx_es2/draw_text.cpp +++ b/ext/native/gfx_es2/draw_text.cpp @@ -41,8 +41,32 @@ enum { MAX_TEXT_HEIGHT = 512 }; -struct TextDrawerFontContext { +class TextDrawerFontContext { +public: + ~TextDrawerFontContext() { + Destroy(); + } + + void Create() { + if (hFont) { + Destroy(); + } + // TODO: Should the 72 really be 96? Oh well... + int nHeight = -MulDiv(height, g_dpi, 72); + hFont = CreateFont(nHeight, 0, 0, 0, bold, 0, + FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, PROOF_QUALITY, + VARIABLE_PITCH, fname.c_str()); + } + void Destroy() { + DeleteObject(hFont); + hFont = 0; + } + HFONT hFont; + std::wstring fname; + int height; + int bold; }; struct TextDrawerContext { @@ -55,6 +79,7 @@ TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(nullpt // These probably shouldn't be state. fontScaleX_ = 1.0f; fontScaleY_ = 1.0f; + last_dpi_scale_ = g_dpi_scale; ctx_ = new TextDrawerContext(); ctx_->hDC = CreateCompatibleDC(NULL); @@ -75,22 +100,12 @@ TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(nullpt } TextDrawer::~TextDrawer() { - for (auto &iter : cache_) { - if (iter.second->texture) - iter.second->texture->Release(); - } - cache_.clear(); - sizeCache_.clear(); + ClearCache(); - for (auto iter = fontMap_.begin(); iter != fontMap_.end(); ++iter) { - DeleteObject(iter->second->hFont); - delete iter->second; - } fontMap_.clear(); DeleteObject(ctx_->hbmBitmap); DeleteDC(ctx_->hDC); - delete ctx_; } @@ -112,17 +127,12 @@ uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { fname = L"Tahoma"; TextDrawerFontContext *font = new TextDrawerFontContext(); + font->bold = FW_LIGHT; + font->height = size; + font->fname = fname; + font->Create(); - float textScale = 1.0f; - - // TODO: Should the 72 really be 96? Oh well... - INT nHeight = -MulDiv( size, (INT)(GetDeviceCaps(ctx_->hDC, LOGPIXELSY) * textScale), 72 ); - int dwBold = FW_LIGHT; ///FW_BOLD - font->hFont = CreateFont(nHeight, 0, 0, 0, dwBold, 0, - FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, PROOF_QUALITY, - VARIABLE_PITCH, fname.c_str()); - fontMap_[fontHash] = font; + fontMap_[fontHash] = std::unique_ptr(font); fontHash_ = fontHash; return fontHash; } @@ -296,6 +306,12 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float target.Flush(true); } +void TextDrawer::RecreateFonts() { + for (auto &iter : fontMap_) { + iter.second->Create(); + } +} + #else TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(NULL) { @@ -304,12 +320,7 @@ TextDrawer::TextDrawer(Draw::DrawContext *thin3d) : thin3d_(thin3d), ctx_(NULL) } TextDrawer::~TextDrawer() { - for (auto &iter : cache_) { - if (iter.second->texture) - iter.second->texture->Release(); - } - cache_.clear(); - sizeCache_.clear(); + ClearCache(); } uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) { @@ -340,6 +351,10 @@ void TextDrawer::SetFont(uint32_t fontHandle) { } +void TextDrawer::RecreateFonts() { + +} + void TextDrawer::MeasureString(const char *str, float *w, float *h) { MeasureString(str, strlen(str), w, h); } @@ -441,6 +456,15 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float #endif +void TextDrawer::ClearCache() { + for (auto &iter : cache_) { + if (iter.second->texture) + iter.second->texture->Release(); + } + cache_.clear(); + sizeCache_.clear(); +} + void TextDrawer::WrapString(std::string &out, const char *str, float maxW) { TextDrawerWordWrapper wrapper(this, str, maxW); out = wrapper.Wrapped(); @@ -476,7 +500,14 @@ void TextDrawer::DrawStringRect(DrawBuffer &target, const char *str, const Bound void TextDrawer::OncePerFrame() { frameCount_++; - // Use a prime number to reduce clashing with other rhythms + // If DPI changed (small-mode, future proper monitor DPI support), drop everything. + if (g_dpi_scale != last_dpi_scale_) { + last_dpi_scale_ = g_dpi_scale; + ClearCache(); + RecreateFonts(); + } + + // Drop old strings. Use a prime number to reduce clashing with other rhythms if (frameCount_ % 23 == 0) { for (auto iter = cache_.begin(); iter != cache_.end();) { if (frameCount_ - iter->second->lastUsedFrame > 100) { diff --git a/ext/native/gfx_es2/draw_text.h b/ext/native/gfx_es2/draw_text.h index f210d62fc7..9ea3e393bf 100644 --- a/ext/native/gfx_es2/draw_text.h +++ b/ext/native/gfx_es2/draw_text.h @@ -46,7 +46,7 @@ enum { // Internal struct but all details in .cpp file (pimpl to avoid pulling in excessive headers here) struct TextDrawerContext; -struct TextDrawerFontContext; +class TextDrawerFontContext; class TextDrawer { public: @@ -68,21 +68,24 @@ public: private: Draw::DrawContext *thin3d_; + void ClearCache(); + void RecreateFonts(); // On DPI change void WrapString(std::string &out, const char *str, float maxWidth); int frameCount_; float fontScaleX_; float fontScaleY_; + float last_dpi_scale_; TextDrawerContext *ctx_; -#ifdef USING_QT_UI +#if defined(USING_QT_UI) std::map fontMap_; -#else - std::map fontMap_; +#elif defined(_WIN32) + std::map> fontMap_; #endif uint32_t fontHash_; // The key is the CityHash of the string xor the fontHash_. - std::map > cache_; - std::map > sizeCache_; + std::map> cache_; + std::map> sizeCache_; };