mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	Gfx: Handle failed creation of D2D text layout
This commit is contained in:
		@@ -318,69 +318,68 @@ void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& forma
 | 
			
		||||
 | 
			
		||||
	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
 | 
			
		||||
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
 | 
			
		||||
	if (SUCCEEDED(hr))
 | 
			
		||||
	if (FAILED(hr)) return;
 | 
			
		||||
 | 
			
		||||
	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
	if (!formatD2D.CreateLayout(
 | 
			
		||||
			str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;
 | 
			
		||||
 | 
			
		||||
	D2D1_POINT_2F drawPosition;
 | 
			
		||||
	drawPosition.x = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		TextFormatD2D& formatD2D = (TextFormatD2D&)format;
 | 
			
		||||
		formatD2D.CreateLayout(
 | 
			
		||||
			str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing);
 | 
			
		||||
 | 
			
		||||
		D2D1_POINT_2F drawPosition;
 | 
			
		||||
		drawPosition.x = [&]()
 | 
			
		||||
		if (!m_AccurateText)
 | 
			
		||||
		{
 | 
			
		||||
			if (!m_AccurateText)
 | 
			
		||||
			const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			switch (formatD2D.GetHorizontalAlignment())
 | 
			
		||||
			{
 | 
			
		||||
				const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
				switch (formatD2D.GetHorizontalAlignment())
 | 
			
		||||
				{
 | 
			
		||||
				case HorizontalAlignment::Left: return rect.X + xOffset;
 | 
			
		||||
				case HorizontalAlignment::Right: return rect.X - xOffset;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return rect.X;
 | 
			
		||||
		} ();
 | 
			
		||||
 | 
			
		||||
		drawPosition.y = [&]()
 | 
			
		||||
		{
 | 
			
		||||
			// GDI+ compatibility.
 | 
			
		||||
			float yPos = rect.Y - formatD2D.m_LineGap;
 | 
			
		||||
			switch (formatD2D.GetVerticalAlignment())
 | 
			
		||||
			{
 | 
			
		||||
			case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
 | 
			
		||||
			case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return yPos;
 | 
			
		||||
		} ();
 | 
			
		||||
 | 
			
		||||
		if (formatD2D.m_Trimming)
 | 
			
		||||
		{
 | 
			
		||||
			D2D1_RECT_F clipRect = ToRectF(rect);
 | 
			
		||||
 | 
			
		||||
			if (m_CanUseAxisAlignClip)
 | 
			
		||||
			{
 | 
			
		||||
				m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				const D2D1_LAYER_PARAMETERS layerParams =
 | 
			
		||||
					D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
				m_Target->PushLayer(layerParams, nullptr);
 | 
			
		||||
			case HorizontalAlignment::Left: return rect.X + xOffset;
 | 
			
		||||
			case HorizontalAlignment::Right: return rect.X - xOffset;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
 | 
			
		||||
		return rect.X;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
		if (formatD2D.m_Trimming)
 | 
			
		||||
	drawPosition.y = [&]()
 | 
			
		||||
	{
 | 
			
		||||
		// GDI+ compatibility.
 | 
			
		||||
		float yPos = rect.Y - formatD2D.m_LineGap;
 | 
			
		||||
		switch (formatD2D.GetVerticalAlignment())
 | 
			
		||||
		{
 | 
			
		||||
			if (m_CanUseAxisAlignClip)
 | 
			
		||||
			{
 | 
			
		||||
				m_Target->PopAxisAlignedClip();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				m_Target->PopLayer();
 | 
			
		||||
			}
 | 
			
		||||
		case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
 | 
			
		||||
		case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return yPos;
 | 
			
		||||
	} ();
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		D2D1_RECT_F clipRect = ToRectF(rect);
 | 
			
		||||
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			const D2D1_LAYER_PARAMETERS layerParams =
 | 
			
		||||
				D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
 | 
			
		||||
			m_Target->PushLayer(layerParams, nullptr);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
 | 
			
		||||
 | 
			
		||||
	if (formatD2D.m_Trimming)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_CanUseAxisAlignClip)
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopAxisAlignedClip();
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			m_Target->PopLayer();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ void TextFormatD2D::Dispose()
 | 
			
		||||
	m_LineGap = 0.0f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::CreateLayout(
 | 
			
		||||
bool TextFormatD2D::CreateLayout(
 | 
			
		||||
	const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation)
 | 
			
		||||
{
 | 
			
		||||
	bool strChanged = false;
 | 
			
		||||
@@ -84,38 +84,38 @@ void TextFormatD2D::CreateLayout(
 | 
			
		||||
	{
 | 
			
		||||
		CanvasD2D::c_DWFactory->CreateTextLayout(
 | 
			
		||||
			str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf());
 | 
			
		||||
		if (!m_TextLayout) return false;
 | 
			
		||||
 | 
			
		||||
		if (m_TextLayout)
 | 
			
		||||
		if (gdiEmulation)
 | 
			
		||||
		{
 | 
			
		||||
			if (gdiEmulation)
 | 
			
		||||
			{
 | 
			
		||||
				Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
				m_TextLayout.As(&textLayout1);
 | 
			
		||||
			Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
 | 
			
		||||
			m_TextLayout.As(&textLayout1);
 | 
			
		||||
 | 
			
		||||
				const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
				const float emOffset = xOffset / 24.0f;
 | 
			
		||||
				const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
				textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
			}
 | 
			
		||||
			const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
 | 
			
		||||
			const float emOffset = xOffset / 24.0f;
 | 
			
		||||
			const DWRITE_TEXT_RANGE range = {0, strLen};
 | 
			
		||||
			textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
			UINT32 lineCount = 0;
 | 
			
		||||
			DWRITE_LINE_METRICS lineMetrics[2];
 | 
			
		||||
			HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
 | 
			
		||||
			if (SUCCEEDED(hr))
 | 
			
		||||
		UINT32 lineCount = 0;
 | 
			
		||||
		DWRITE_LINE_METRICS lineMetrics[2];
 | 
			
		||||
		HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
 | 
			
		||||
		if (SUCCEEDED(hr))
 | 
			
		||||
		{
 | 
			
		||||
			// If only one line is visible, disable wrapping so that as much text as possible is shown
 | 
			
		||||
			// after trimming.
 | 
			
		||||
			// TODO: Fix this for when more than one line is visible.
 | 
			
		||||
			if (lineCount >= 2 &&
 | 
			
		||||
				lineMetrics[0].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].isTrimmed &&
 | 
			
		||||
				lineMetrics[1].height == 0.0f)
 | 
			
		||||
			{
 | 
			
		||||
				// If only one line is visible, disable wrapping so that as much text as possible is shown
 | 
			
		||||
				// after trimming.
 | 
			
		||||
				// TODO: Fix this for when more than one line is visible.
 | 
			
		||||
				if (lineCount >= 2 &&
 | 
			
		||||
					lineMetrics[0].isTrimmed &&
 | 
			
		||||
					lineMetrics[1].isTrimmed &&
 | 
			
		||||
					lineMetrics[1].height == 0.0f)
 | 
			
		||||
				{
 | 
			
		||||
					m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
 | 
			
		||||
				}
 | 
			
		||||
				m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TextFormatD2D::SetProperties(
 | 
			
		||||
 
 | 
			
		||||
@@ -55,8 +55,8 @@ private:
 | 
			
		||||
 | 
			
		||||
	// Creates a new DirectWrite text layout if |str| has changed since last call. Since creating
 | 
			
		||||
	// the layout is costly, it is more efficient to keep reusing the text layout until the text
 | 
			
		||||
	// changes.
 | 
			
		||||
	void CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
 | 
			
		||||
	// changes. Returns true if the layout is valid for use.
 | 
			
		||||
	bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
 | 
			
		||||
 | 
			
		||||
	DWRITE_TEXT_METRICS GetMetrics(
 | 
			
		||||
		const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user