diff options
author | Neil <nyamatongwe@gmail.com> | 2022-03-12 10:26:33 +1100 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2022-03-12 10:26:33 +1100 |
commit | 3064b730d2e912c7540a86341b0a7d1693a20690 (patch) | |
tree | 8f20614b439a669931ce64dac1156649129de8b1 /win32 | |
parent | 73ae9e3d2ad7fddbe8945deb0647dd7597d58c0a (diff) | |
download | scintilla-mirror-3064b730d2e912c7540a86341b0a7d1693a20690.tar.gz |
Feature [feature-requests:#1432] Support per-monitor text rendering parameters
and update when changed by user.
Includes code from Zufu Liu.
Diffstat (limited to 'win32')
-rw-r--r-- | win32/PlatWin.cxx | 53 | ||||
-rw-r--r-- | win32/PlatWin.h | 9 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 73 |
3 files changed, 100 insertions, 35 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 3d8595b1d..af1e41b5f 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -72,8 +72,6 @@ UINT CodePageFromCharSet(CharacterSet characterSet, UINT documentCodePage) noexc #if defined(USE_D2D) IDWriteFactory *pIDWriteFactory = nullptr; ID2D1Factory *pD2DFactory = nullptr; -IDWriteRenderingParams *defaultRenderingParams = nullptr; -IDWriteRenderingParams *customClearTypeRenderingParams = nullptr; D2D1_DRAW_TEXT_OPTIONS d2dDrawTextOptions = D2D1_DRAW_TEXT_OPTIONS_NONE; static HMODULE hDLLD2D {}; @@ -123,24 +121,6 @@ void LoadD2DOnce() noexcept { reinterpret_cast<IUnknown**>(&pIDWriteFactory)); } } - - if (pIDWriteFactory) { - const HRESULT hr = pIDWriteFactory->CreateRenderingParams(&defaultRenderingParams); - if (SUCCEEDED(hr)) { - unsigned int clearTypeContrast = 0; - if (::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0)) { - - FLOAT gamma; - if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200) - gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f; - else - gamma = defaultRenderingParams->GetGamma(); - - pIDWriteFactory->CreateCustomRenderingParams(gamma, defaultRenderingParams->GetEnhancedContrast(), defaultRenderingParams->GetClearTypeLevel(), - defaultRenderingParams->GetPixelGeometry(), defaultRenderingParams->GetRenderingMode(), &customClearTypeRenderingParams); - } - } - } } bool LoadD2D() { @@ -1294,7 +1274,7 @@ constexpr D2D1_RECT_F RectangleInset(D2D1_RECT_F rect, FLOAT inset) noexcept { class BlobInline; -class SurfaceD2D : public Surface { +class SurfaceD2D : public Surface, public ISetRenderingParams { SurfaceMode mode; ID2D1RenderTarget *pRenderTarget = nullptr; @@ -1304,8 +1284,10 @@ class SurfaceD2D : public Surface { ID2D1SolidColorBrush *pBrush = nullptr; - FontQuality fontQuality = FontQuality::QualityMask; + static constexpr FontQuality invalidFontQuality = FontQuality::QualityMask; + FontQuality fontQuality = invalidFontQuality; int logPixelsY = USER_DEFAULT_SCREEN_DPI; + std::shared_ptr<RenderingParams> renderingParams; void Clear() noexcept; void SetFontQuality(FontQuality extraFontFlag); @@ -1379,6 +1361,8 @@ public: void PopClip() override; void FlushCachedState() override; void FlushDrawing() override; + + void SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) override; }; SurfaceD2D::SurfaceD2D() noexcept { @@ -1430,7 +1414,7 @@ void SurfaceD2D::Release() noexcept { } void SurfaceD2D::SetScale(WindowID wid) noexcept { - fontQuality = FontQuality::QualityMask; + fontQuality = invalidFontQuality; logPixelsY = DpiForWindow(wid); } @@ -1458,7 +1442,9 @@ void SurfaceD2D::Init(SurfaceID sid, WindowID wid) { } std::unique_ptr<Surface> SurfaceD2D::AllocatePixMap(int width, int height) { - return std::make_unique<SurfaceD2D>(pRenderTarget, width, height, mode, logPixelsY); + std::unique_ptr<SurfaceD2D> surf = std::make_unique<SurfaceD2D>(pRenderTarget, width, height, mode, logPixelsY); + surf->SetRenderingParams(renderingParams); + return surf; } void SurfaceD2D::SetMode(SurfaceMode mode_) { @@ -1485,15 +1471,14 @@ void SurfaceD2D::D2DPenColourAlpha(ColourRGBA fore) noexcept { } void SurfaceD2D::SetFontQuality(FontQuality extraFontFlag) { - if (fontQuality != extraFontFlag) { + if ((fontQuality != extraFontFlag) && renderingParams) { fontQuality = extraFontFlag; const D2D1_TEXT_ANTIALIAS_MODE aaMode = DWriteMapFontQuality(extraFontFlag); - - if (aaMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && customClearTypeRenderingParams) - pRenderTarget->SetTextRenderingParams(customClearTypeRenderingParams); - else if (defaultRenderingParams) - pRenderTarget->SetTextRenderingParams(defaultRenderingParams); - + if (aaMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && renderingParams->customRenderingParams) { + pRenderTarget->SetTextRenderingParams(renderingParams->customRenderingParams.get()); + } else if (renderingParams->defaultRenderingParams) { + pRenderTarget->SetTextRenderingParams(renderingParams->defaultRenderingParams.get()); + } pRenderTarget->SetTextAntialiasMode(aaMode); } } @@ -2629,6 +2614,10 @@ void SurfaceD2D::FlushDrawing() { } } +void SurfaceD2D::SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) { + renderingParams = renderingParams_; +} + #endif std::unique_ptr<Surface> Surface::Allocate(Technology technology) { @@ -3863,8 +3852,6 @@ void Platform_Initialise(void *hInstance) noexcept { void Platform_Finalise(bool fromDllMain) noexcept { #if defined(USE_D2D) if (!fromDllMain) { - ReleaseUnknown(defaultRenderingParams); - ReleaseUnknown(customClearTypeRenderingParams); ReleaseUnknown(pIDWriteFactory); ReleaseUnknown(pD2DFactory); if (hDLLDWrite) { diff --git a/win32/PlatWin.h b/win32/PlatWin.h index 68b5dd9ef..893618b38 100644 --- a/win32/PlatWin.h +++ b/win32/PlatWin.h @@ -53,6 +53,15 @@ HCURSOR LoadReverseArrowCursor(UINT dpi) noexcept; extern bool LoadD2D(); extern ID2D1Factory *pD2DFactory; extern IDWriteFactory *pIDWriteFactory; + +struct RenderingParams { + std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> defaultRenderingParams; + std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> customRenderingParams; +}; + +struct ISetRenderingParams { + virtual void SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) = 0; +}; #endif } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 7bb8d43db..52473bfa6 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -318,6 +318,9 @@ class ScintillaWin : #if defined(USE_D2D) ID2D1RenderTarget *pRenderTarget; bool renderTargetValid; + // rendering parameters for current monitor + HMONITOR hCurrentMonitor; + std::shared_ptr<RenderingParams> renderingParams; #endif explicit ScintillaWin(HWND hwnd); @@ -330,6 +333,7 @@ class ScintillaWin : void Finalise() override; #if defined(USE_D2D) + bool UpdateRenderingParams(bool force) noexcept; void EnsureRenderTarget(HDC hdc); #endif void DropRenderTarget() noexcept; @@ -354,6 +358,8 @@ class ScintillaWin : Sci::Position TargetAsUTF8(char *text) const; Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const; + void SetRenderingParams(Surface *psurf) const; + bool PaintDC(HDC hdc); sptr_t WndPaint(); @@ -533,6 +539,7 @@ ScintillaWin::ScintillaWin(HWND hwnd) { #if defined(USE_D2D) pRenderTarget = nullptr; renderTargetValid = true; + hCurrentMonitor = {}; #endif caret.period = ::GetCaretBlinkTime(); @@ -577,6 +584,38 @@ void ScintillaWin::Finalise() { #if defined(USE_D2D) +bool ScintillaWin::UpdateRenderingParams(bool force) noexcept { + if (!renderingParams) { + renderingParams = std::make_shared<RenderingParams>(); + } + HMONITOR monitor = ::MonitorFromWindow(MainHWND(), MONITOR_DEFAULTTONEAREST); + if (!force && monitor == hCurrentMonitor && renderingParams->defaultRenderingParams) { + return false; + } + + IDWriteRenderingParams *monitorRenderingParams = nullptr; + IDWriteRenderingParams *customClearTypeRenderingParams = nullptr; + const HRESULT hr = pIDWriteFactory->CreateMonitorRenderingParams(monitor, &monitorRenderingParams); + UINT clearTypeContrast = 0; + if (SUCCEEDED(hr) && ::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0) != 0) { + if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200) { + const FLOAT gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f; + pIDWriteFactory->CreateCustomRenderingParams(gamma, + monitorRenderingParams->GetEnhancedContrast(), + monitorRenderingParams->GetClearTypeLevel(), + monitorRenderingParams->GetPixelGeometry(), + monitorRenderingParams->GetRenderingMode(), + &customClearTypeRenderingParams); + } + } + + hCurrentMonitor = monitor; + renderingParams->defaultRenderingParams.reset(monitorRenderingParams); + renderingParams->customRenderingParams.reset(customClearTypeRenderingParams); + return true; +} + + void ScintillaWin::EnsureRenderTarget(HDC hdc) { if (!renderTargetValid) { DropRenderTarget(); @@ -646,7 +685,6 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) { } #endif - void ScintillaWin::DropRenderTarget() noexcept { #if defined(USE_D2D) ReleaseUnknown(pRenderTarget); @@ -873,6 +911,17 @@ Sci::Position ScintillaWin::EncodedFromUTF8(const char *utf8, char *encoded) con } } +void ScintillaWin::SetRenderingParams([[maybe_unused]] Surface *psurf) const { +#if defined(USE_D2D) + if (psurf) { + ISetRenderingParams *setDrawingParams = dynamic_cast<ISetRenderingParams *>(psurf); + if (setDrawingParams) { + setDrawingParams->SetRenderingParams(renderingParams); + } + } +#endif +} + bool ScintillaWin::PaintDC(HDC hdc) { if (technology == Technology::Default) { AutoSurface surfaceWindow(hdc, this); @@ -886,6 +935,7 @@ bool ScintillaWin::PaintDC(HDC hdc) { if (pRenderTarget) { AutoSurface surfaceWindow(pRenderTarget, this); if (surfaceWindow) { + SetRenderingParams(surfaceWindow); pRenderTarget->BeginDraw(); Paint(surfaceWindow, rcPaint); surfaceWindow->Release(); @@ -1824,9 +1874,11 @@ sptr_t ScintillaWin::SciMessage(Message iMessage, uptr_t wParam, sptr_t lParam) if (technology != technologyNew) { if (technologyNew > Technology::Default) { #if defined(USE_D2D) - if (!LoadD2D()) + if (!LoadD2D()) { // Failed to load Direct2D or DirectWrite so no effect return 0; + } + UpdateRenderingParams(true); #else return 0; #endif @@ -1952,6 +2004,12 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case WM_SETTINGCHANGE: //Platform::DebugPrintf("Setting Changed\n"); +#if defined(USE_D2D) + if (technology != Technology::Default) { + UpdateRenderingParams(true); + Redraw(); + } +#endif UpdateBaseElements(); InvalidateStyleData(); // Get Intellimouse scroll line parameters @@ -2016,7 +2074,17 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case WM_NCLBUTTONDOWN: case WM_SYSCOMMAND: case WM_WINDOWPOSCHANGING: + return ::DefWindowProc(MainHWND(), msg, wParam, lParam); + case WM_WINDOWPOSCHANGED: +#if defined(USE_D2D) + if (technology != Technology::Default) { + if (UpdateRenderingParams(false)) { + DropGraphics(); + Redraw(); + } + } +#endif return ::DefWindowProc(MainHWND(), msg, wParam, lParam); case WM_GETTEXTLENGTH: @@ -3528,6 +3596,7 @@ LRESULT PASCAL ScintillaWin::CTWndProc( #endif } surfaceWindow->SetMode(sciThis->CurrentSurfaceMode()); + sciThis->SetRenderingParams(surfaceWindow.get()); sciThis->ct.PaintCT(surfaceWindow.get()); #if defined(USE_D2D) if (pCTRenderTarget) |