From b27bf1ee6337f23b23206de8bad31908d4b58de3 Mon Sep 17 00:00:00 2001 From: Brian Ferguson Date: Thu, 25 Jul 2013 14:53:02 -0600 Subject: [PATCH] Added "AccurateText" option [Rainmeter] section of a skin. When AccurateText=0 (default) and UseD2D=0, inaccurate GDI+ measuring of text is used When AccurateText=1 and UseD2D=0, Accurate measuring occurs similar to D2D When AccurateText=0 and UseD2D=1, D2D adds padding to the text similar to GDI+ When AccurateText=1 and UseD2D=1, Accurate measuring occurs using D2D --- Common/Gfx/Canvas.cpp | 3 ++- Common/Gfx/Canvas.h | 4 ++++ Common/Gfx/CanvasD2D.cpp | 36 +++++++++++++++++++++++++++++++----- Common/Gfx/CanvasGDIP.cpp | 39 ++++++++++++++++++++++++++++++++++++--- Library/MeterWindow.cpp | 3 +++ Library/MeterWindow.h | 1 + 6 files changed, 77 insertions(+), 9 deletions(-) diff --git a/Common/Gfx/Canvas.cpp b/Common/Gfx/Canvas.cpp index 3555425b..b2fe0c58 100644 --- a/Common/Gfx/Canvas.cpp +++ b/Common/Gfx/Canvas.cpp @@ -22,7 +22,8 @@ namespace Gfx { Canvas::Canvas() : m_W(), - m_H() + m_H(), + m_AccurateText(false) { } diff --git a/Common/Gfx/Canvas.h b/Common/Gfx/Canvas.h index f45ab82c..9f3f50c4 100644 --- a/Common/Gfx/Canvas.h +++ b/Common/Gfx/Canvas.h @@ -35,6 +35,8 @@ public: int GetW() const { return m_W; } int GetH() const { return m_H; } + void SetAccurateText(bool option) { m_AccurateText = option; } + // Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been // called and has not yet been matched by a correspoding call to EndDraw. virtual void Resize(int w, int h); @@ -86,6 +88,8 @@ protected: int m_W; int m_H; + bool m_AccurateText; + private: Canvas(const Canvas& other) {} }; diff --git a/Common/Gfx/CanvasD2D.cpp b/Common/Gfx/CanvasD2D.cpp index 05e3e3d5..c921ea6a 100644 --- a/Common/Gfx/CanvasD2D.cpp +++ b/Common/Gfx/CanvasD2D.cpp @@ -314,7 +314,7 @@ void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& forma formatD2D.CreateLayout(str, strLen, rect.Width, rect.Height); m_Target->DrawTextLayout( - D2D1::Point2F(right ? rect.X - 2 : rect.X + 2.0f, rect.Y - 1.0f), + D2D1::Point2F(m_AccurateText ? rect.X : right ? rect.X - 3.0f : rect.X + 3.0f, rect.Y - 1.0f), formatD2D.m_TextLayout.Get(), solidBrush.Get()); } @@ -334,8 +334,21 @@ bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& fo { DWRITE_TEXT_METRICS metrics; textLayout->GetMetrics(&metrics); - rect.Width = metrics.width + 5.0f; - rect.Height = metrics.height + 1.0f; // 1.0f to get same result as GDI+. + + if (!m_AccurateText) + { + float size = 0.0f; + textLayout->GetFontSize(0, &size); + + rect.Width = floor(metrics.width + (size / 2.05f) + 0.65f); + rect.Height = floor(metrics.height + 1.5f); + } + else + { + rect.Width = metrics.width; + rect.Height = metrics.height; + } + return true; } @@ -358,8 +371,21 @@ bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextForma { DWRITE_TEXT_METRICS metrics; textLayout->GetMetrics(&metrics); - rect.Width = metrics.width + 5.0f; - rect.Height = metrics.height + 1.0f; // 1.0f to get same result as GDI+. + + if (!m_AccurateText) + { + float size = 0.0f; + textLayout->GetFontSize(0, &size); + + rect.Width = floor(metrics.width + (size / 2.05f) + 0.65f); + rect.Height = floor(metrics.height + 1.5f); + } + else + { + rect.Width = metrics.width; + rect.Height = metrics.height + 1.0f; + } + lines = metrics.lineCount; return true; } diff --git a/Common/Gfx/CanvasGDIP.cpp b/Common/Gfx/CanvasGDIP.cpp index 48f2c149..23404759 100644 --- a/Common/Gfx/CanvasGDIP.cpp +++ b/Common/Gfx/CanvasGDIP.cpp @@ -160,21 +160,45 @@ void CanvasGDIP::Clear(const Gdiplus::Color& color) void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) { Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); + + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + m_Graphics->DrawString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, &stringFormat, &brush); + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &brush); } bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) { Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); + + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + const Gdiplus::Status status = m_Graphics->MeasureString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, &stringFormat, &rect); + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &rect); + return status == Gdiplus::Ok; } bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) { Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat; + Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic(); // Set trimming and format temporarily. const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming(); @@ -183,9 +207,18 @@ bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextForm const INT stringFormatFlags = stringFormat.GetFormatFlags(); stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip); + if (m_AccurateText) + { + tStringFormat.SetTrimming(stringFormat.GetTrimming()); + tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags()); + tStringFormat.SetAlignment(stringFormat.GetAlignment()); + tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment()); + } + INT linesFilled = 0; const Gdiplus::Status status = m_Graphics->MeasureString( - str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, &stringFormat, &rect, nullptr, &linesFilled); + str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect, + m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled); lines = linesFilled; // Restore old options. diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 0f014f77..7e1d4c2f 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -2077,6 +2077,9 @@ bool MeterWindow::ReadSkin() // Read options from Rainmeter.ini. ReadOptions(); + m_AccurateText = 0!=m_Parser.ReadInt(L"Rainmeter", L"AccurateText", 0); + m_Canvas->SetAccurateText(m_AccurateText); + // Check the version UINT appVersion = m_Parser.ReadUInt(L"Rainmeter", L"AppVersion", 0); if (appVersion > RAINMETER_VERSION) diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index c4f8d8b6..cb31e328 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -324,6 +324,7 @@ private: void CreateDoubleBuffer(int cx, int cy); Gfx::Canvas* m_Canvas; + bool m_AccurateText; ConfigParser m_Parser;