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
This commit is contained in:
Brian Ferguson 2013-07-25 14:53:02 -06:00
parent 3bf2bd3902
commit b27bf1ee63
6 changed files with 77 additions and 9 deletions

View File

@ -22,7 +22,8 @@ namespace Gfx {
Canvas::Canvas() :
m_W(),
m_H()
m_H(),
m_AccurateText(false)
{
}

View File

@ -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) {}
};

View File

@ -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;
}

View File

@ -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.

View File

@ -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)

View File

@ -324,6 +324,7 @@ private:
void CreateDoubleBuffer(int cx, int cy);
Gfx::Canvas* m_Canvas;
bool m_AccurateText;
ConfigParser m_Parser;