/* Copyright (C) 2013 Birunthan Mohanathas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "TextFormatD2D.h" #include "CanvasD2D.h" #include "Util/DWriteHelpers.h" namespace Gfx { TextFormatD2D::TextFormatD2D() : m_TextFormat(), m_TextLayout(), m_InlineEllipsis() { } TextFormatD2D::~TextFormatD2D() { Dispose(); } void TextFormatD2D::Dispose() { if (m_TextFormat) { m_TextFormat->Release(); m_TextFormat = nullptr; } if (m_TextLayout) { m_TextLayout->Release(); m_TextLayout = nullptr; } if (m_InlineEllipsis) { m_InlineEllipsis->Release(); m_InlineEllipsis = nullptr; } } void TextFormatD2D::CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH) { bool strChanged = false; if (strLen != m_LastString.length() || memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0) { strChanged = true; m_LastString.assign(str, strLen); } if (m_TextLayout && !strChanged) { if (maxW != m_TextLayout->GetMaxWidth()) { m_TextLayout->SetMaxWidth(maxW); } if (maxH != m_TextLayout->GetMaxHeight()) { m_TextLayout->SetMaxWidth(maxH); } } else { if (m_TextLayout) { m_TextLayout->Release(); m_TextLayout = nullptr; } CanvasD2D::c_DWFactory->CreateTextLayout(str, strLen, m_TextFormat, maxW, maxH, &m_TextLayout); } } void TextFormatD2D::SetProperties( const WCHAR* fontFamily, int size, bool bold, bool italic, const FontCollection* fontCollection) { Dispose(); HRESULT hr = E_FAIL; // |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font // using the GDI family name and then create a text format using the DirectWrite family name // obtained from it. WCHAR dwFamilyName[LF_FACESIZE]; DWRITE_FONT_WEIGHT dwFontWeight; DWRITE_FONT_STYLE dwFontStyle; DWRITE_FONT_STRETCH dwFontStretch; if (Util::GetDWritePropertiesFromGDIProperties( CanvasD2D::c_DWFactory, fontFamily, bold, italic, dwFontWeight, dwFontStyle, dwFontStretch, dwFamilyName, _countof(dwFamilyName))) { hr = CanvasD2D::c_DWFactory->CreateTextFormat( dwFamilyName, nullptr, dwFontWeight, dwFontStyle, dwFontStretch, size * (4.0f / 3.0f), L"", &m_TextFormat); } if (FAILED(hr)) { IDWriteFontCollection* dwriteFontCollection = nullptr; auto fontCollectionD2D = (FontCollectionD2D*)fontCollection; // If |fontFamily| is not in the system collection, use the font collection from // |fontCollectionD2D| if possible. // // TODO: Need to check GDI family names of the collection in |fontCollectionD2D|. if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory, fontFamily) && (fontCollectionD2D && fontCollectionD2D->InitializeCollection())) { dwriteFontCollection = fontCollectionD2D->m_Collection; } // Fallback in case above fails. hr = CanvasD2D::c_DWFactory->CreateTextFormat( fontFamily, dwriteFontCollection, bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR, italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, size * (4.0f / 3.0f), L"", &m_TextFormat); } if (SUCCEEDED(hr)) { SetHorizontalAlignment(GetHorizontalAlignment()); SetVerticalAlignment(GetVerticalAlignment()); } else { Dispose(); } } void TextFormatD2D::SetTrimming(bool trim) { IDWriteInlineObject* inlineObject = nullptr; DWRITE_TRIMMING trimming = {}; DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP; if (trim) { if (!m_InlineEllipsis) { CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign(m_TextFormat, &m_InlineEllipsis); } inlineObject = m_InlineEllipsis; trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER; wordWrapping = DWRITE_WORD_WRAPPING_WRAP; } m_TextFormat->SetTrimming(&trimming, inlineObject); m_TextFormat->SetWordWrapping(wordWrapping); } void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment) { __super::SetHorizontalAlignment(alignment); if (m_TextFormat) { m_TextFormat->SetTextAlignment( (alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING : (alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER : DWRITE_TEXT_ALIGNMENT_TRAILING); } } void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment) { __super::SetVerticalAlignment(alignment); if (m_TextFormat) { m_TextFormat->SetParagraphAlignment( (alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR : (alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER : DWRITE_PARAGRAPH_ALIGNMENT_FAR); } } } // namespace Gfx