diff --git a/.gitignore b/.gitignore
index fd193a46b25..fc0cf0a396f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ build/
bld/
[Bb]in/
[Oo]bj/
+Generated Files/
# Visual Studio 2015 cache/options directory
.vs/
diff --git a/Directory.Build.props b/Directory.Build.props
index 4f6d23454b8..ca81a986166 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -65,7 +65,7 @@
-
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
index fc33f4fc0c7..1f77bdbfbd9 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
@@ -282,6 +282,7 @@
+
@@ -524,6 +525,7 @@
+
Designer
@@ -580,6 +582,9 @@
+
+ DirectWriteTextBlockPage.xaml
+
TabViewPage.xaml
@@ -956,6 +961,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
@@ -1437,6 +1446,10 @@
{d4d78cba-b238-4794-89a0-4f1a2d8fea97}
Microsoft.Toolkit.Uwp.UI.Controls.Graph
+
+ {d4c7ac54-826a-4412-8461-a7c7fd86534b}
+ Microsoft.Toolkit.Uwp.UI.Controls.WinRT
+
{e9faabfb-d726-42c1-83c1-cb46a29fea81}
Microsoft.Toolkit.Uwp.UI.Controls
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlock.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlock.png
new file mode 100644
index 00000000000..55f02676d95
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlock.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockCode.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockCode.bind
new file mode 100644
index 00000000000..4a3f86e333f
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockCode.bind
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml
new file mode 100644
index 00000000000..20d2538e161
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml.cs
new file mode 100644
index 00000000000..cffb3222941
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/DirectWriteTextBlock/DirectWriteTextBlockPage.xaml.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class DirectWriteTextBlockPage : Page
+ {
+ public DirectWriteTextBlockPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
index 1dcbea4074b..1be66093060 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
@@ -438,6 +438,17 @@
"XamlCodeFile": "FocusTrackerXaml.bind",
"Icon": "/SamplePages/FocusTracker/FocusTracker.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/developer-tools/FocusTracker.md"
+ },
+ {
+ "Name": "DirectWriteTextBlock",
+ "Type": "DirectWriteTextBlockPage",
+ "About": "DirectWriteTextBlock is a text block like class which generates an image using the DirectWrite API and displays it. Display vertically oriented text with it.",
+ "CodeUrl": "https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock",
+ "XamlCodeFile": "DirectWriteTextBlockCode.bind",
+ "Icon": "/SamplePages/DirectWriteTextBlock/DirectWriteTextBlock.png",
+ "ApiCheck": "Windows.UI.Xaml.Controls.ColorPicker",
+ "BadgeUpdateVersionRequired": "April 2018 Update required",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/DirectWriteTextBlock.md"
}
]
},
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.cpp
new file mode 100644
index 00000000000..671b29377a1
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.cpp
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
+#include
+#include
+#include
+#include "DirectWriteFontFileEnumerator.h"
+#include "DirectWriteFontCollectionLoader.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+winrt::com_ptr DirectWriteFontCollectionLoader::s_comInstance;
+
+DirectWriteFontCollectionLoader::DirectWriteFontCollectionLoader()
+{
+}
+
+DirectWriteFontCollectionLoader::~DirectWriteFontCollectionLoader()
+{
+}
+
+bool DirectWriteFontCollectionLoader::HasCustomFontFamily(Platform::String^ xamlFontFamily)
+{
+ // is there a .ttf in the path?
+ std::wstring wstringPath{ xamlFontFamily->Data() };
+ std::transform(wstringPath.begin(), wstringPath.end(), wstringPath.begin(), towlower);
+ auto foundCustomFontFile = wstringPath.find(L".ttf#", 0);
+ return foundCustomFontFile != std::wstring::npos;
+}
+
+void DirectWriteFontCollectionLoader::ParseXamlFontFamily(_In_ Platform::String^ xamlFontFamily, _Out_ DirectWriteUniversalPackageFontData& parsedFont)
+{
+ parsedFont = {};
+ std::wstring wstringPath{ xamlFontFamily->Data() };
+ auto delimLocation = wstringPath.find(L'#');
+ if (delimLocation != std::wstring::npos)
+ {
+ auto path = wstringPath.substr(0, delimLocation);
+ std::replace(path.begin(), path.end(), L'/', L'\\');
+ parsedFont.packageFontFilePath = path;
+ parsedFont.customFontName = wstringPath.substr(delimLocation + 1);
+ }
+}
+
+bool DirectWriteFontCollectionLoader::FindCachedEnumerator(Platform::String^ xamlFontFamily, winrt::com_ptr& enumerator)
+{
+ for (auto& entry : m_fontEnumerators)
+ {
+ if (entry.customFont->Equals(xamlFontFamily))
+ {
+ enumerator = entry.enumerator;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+IFACEMETHODIMP DirectWriteFontCollectionLoader::CreateEnumeratorFromKey(_In_ IDWriteFactory* factory, void const* collectionKey, unsigned int collectionKeySize, _Outptr_ IDWriteFontFileEnumerator** fontFileEnumerator)
+try
+{
+ *fontFileEnumerator = nullptr;
+ auto xamlFontFamily = ref new Platform::String(reinterpret_cast(collectionKey), collectionKeySize);
+
+ if (HasCustomFontFamily(xamlFontFamily))
+ {
+ winrt::com_ptr cachedEnumerator;
+ if (!FindCachedEnumerator(xamlFontFamily, cachedEnumerator))
+ {
+ auto enumerator{ winrt::make_self() };
+ DirectWriteUniversalPackageFontData parseData = {};
+ ParseXamlFontFamily(xamlFontFamily, parseData);
+ winrt::check_hresult(enumerator->Initialize(factory, parseData));
+
+ FontEnumeratorEntry entry = {};
+ entry.customFont = xamlFontFamily;
+ entry.enumerator = enumerator;
+ m_fontEnumerators.push_back(std::move(entry));
+ cachedEnumerator = enumerator;
+ }
+
+ winrt::check_hresult(cachedEnumerator->QueryInterface(IID_PPV_ARGS(fontFileEnumerator)));
+ }
+ else
+ {
+ winrt::throw_hresult(E_INVALIDARG);
+ }
+
+ return S_OK;
+}
+catch (...)
+{
+ return winrt::to_hresult();
+}
+
+winrt::com_ptr& DirectWriteFontCollectionLoader::GetInstance()
+{
+ if (!s_comInstance)
+ {
+ s_comInstance = winrt::make();
+ }
+
+ return s_comInstance;
+}
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.h
new file mode 100644
index 00000000000..1bc03199654
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontCollectionLoader.h
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+#include "DirectWriteUniversalPackageFontData.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+///
+/// This is just to glue together a custom font file in the Universal Windows app package
+/// to a custom DWrite Font. All it does is provide an enumerator that returns 1 font (the custom font)
+/// and doesn't support things like font fallbacks.
+///
+struct DirectWriteFontCollectionLoader : winrt::implements
+{
+public:
+ DirectWriteFontCollectionLoader();
+ virtual ~DirectWriteFontCollectionLoader();
+
+ ///
+ /// Create the enumerator to the Universal Windows Application package.
+ ///
+ IFACEMETHOD(CreateEnumeratorFromKey)(
+ _In_ IDWriteFactory* factory,
+ void const* collectionKey, // XAML FontFamily Syntax (something.ttf)#font
+ unsigned int collectionKeySize,
+ _Outptr_ IDWriteFontFileEnumerator** fontFileEnumerator
+ );
+
+ ///
+ /// This sees if the incoming XAML FontFamily value has something that looks like
+ /// a custom font file like foo.ttf#bar
+ ///
+ static bool HasCustomFontFamily(Platform::String^ xamlFontFamily);
+
+ ///
+ /// This parses something that looks like /foo/bar.ttf#baz into the ttf path and the font name (baz).
+ ///
+ static void ParseXamlFontFamily(Platform::String^ xamlFontFamily, _Out_ DirectWriteUniversalPackageFontData& parsedFont);
+
+ ///
+ /// Get the singleton loader.
+ ///
+ static winrt::com_ptr& GetInstance();
+
+private:
+ struct FontEnumeratorEntry
+ {
+ Platform::String^ customFont;
+ winrt::com_ptr enumerator;
+ };
+
+ // enumerators are cached due to memory usages.
+ bool FindCachedEnumerator(Platform::String^ xamlFontFamily, winrt::com_ptr& enumerator);
+
+ std::vector m_fontEnumerators;
+ static winrt::com_ptr s_comInstance;
+};
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.cpp
new file mode 100644
index 00000000000..a48e8870b38
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.cpp
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
+#include "DirectWriteFontFileEnumerator.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+using namespace Windows::Storage;
+
+DirectWriteFontFileEnumerator::DirectWriteFontFileEnumerator()
+{
+}
+
+DirectWriteFontFileEnumerator::~DirectWriteFontFileEnumerator()
+{
+}
+
+HRESULT DirectWriteFontFileEnumerator::Initialize(_In_ IDWriteFactory* factory, const DirectWriteUniversalPackageFontData& packageFont)
+try
+{
+ if ((factory == nullptr) || packageFont.packageFontFilePath.empty() || packageFont.customFontName.empty())
+ {
+ winrt::throw_hresult(E_INVALIDARG);
+ }
+
+ m_factory.attach(factory);
+ m_packageFontArgs = packageFont;
+ return S_OK;
+}
+catch (...)
+{
+ return winrt::to_hresult();
+}
+
+IFACEMETHODIMP DirectWriteFontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile)
+try
+{
+ *hasCurrentFile = FALSE;
+ if (!m_enumerated)
+ {
+ m_currentFontFile = nullptr;
+ auto uwappStorage = Windows::ApplicationModel::Package::Current->InstalledLocation;
+ std::wstring filePath{ uwappStorage->Path->Data() };
+ filePath.append(m_packageFontArgs.packageFontFilePath);
+ winrt::check_hresult(m_factory->CreateFontFileReference(filePath.c_str(), nullptr, m_currentFontFile.put()));
+
+ *hasCurrentFile = TRUE;
+ m_enumerated = true;
+ }
+
+ return S_OK;
+}
+catch (...)
+{
+ return winrt::to_hresult();
+}
+
+IFACEMETHODIMP DirectWriteFontFileEnumerator::GetCurrentFontFile(_Outptr_ IDWriteFontFile** fontFile)
+try
+{
+ m_currentFontFile.copy_to(fontFile);
+ return S_OK;
+}
+catch (...)
+{
+ return winrt::to_hresult();
+}
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.h
new file mode 100644
index 00000000000..548703af69f
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteFontFileEnumerator.h
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+#include "DirectWriteUniversalPackageFontData.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+///
+/// This is an enumerator that basically just enumerates 1 custom font into DWrite from the Universal Windows App package.
+/// It's extremely simplistic and basically just connects the Universal App Package files to DWrite.
+///
+struct DirectWriteFontFileEnumerator : winrt::implements
+{
+public:
+ DirectWriteFontFileEnumerator();
+ virtual ~DirectWriteFontFileEnumerator();
+
+ ///
+ /// This is called consecutively by DWrite until we return FALSE to hasCurrentFile to enumerate the custom
+ /// font
+ ///
+ IFACEMETHOD(MoveNext)(_Out_ BOOL* hasCurrentFile);
+
+ ///
+ /// This is called by DWrite to get the custom font file.
+ ///
+ IFACEMETHOD(GetCurrentFontFile)(_Outptr_ IDWriteFontFile** fontFile);
+
+ ///
+ /// Initializes the enumerator
+ ///
+ HRESULT Initialize(_In_ IDWriteFactory* factory, const DirectWriteUniversalPackageFontData& packageFont);
+
+private:
+ winrt::com_ptr m_factory;
+ winrt::com_ptr m_currentFontFile;
+ DirectWriteUniversalPackageFontData m_packageFontArgs = {};
+ bool m_enumerated = false;
+};
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.cpp
new file mode 100644
index 00000000000..fabc73217b5
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.cpp
@@ -0,0 +1,335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
+#include "DirectWriteRenderArgBuilder.h"
+#include "DirectWriteResourceManager.h"
+#include "DirectWriteFontCollectionLoader.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+using namespace Platform;
+using namespace Windows::UI;
+using namespace Windows::UI::Text;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::Globalization;
+using namespace Windows::Graphics::Display;
+using namespace Windows::Foundation;
+
+DirectWriteRenderArgBuilder::DirectWriteRenderArgBuilder()
+{
+ // default values
+ m_builtArgs.availableHeight = 0;
+ m_builtArgs.availableWidth = 0;
+ m_builtArgs.flowDirection = DWRITE_FLOW_DIRECTION::DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT;
+ m_builtArgs.fontFamily = ref new String(L"Segoe UI");
+ m_builtArgs.fontSize = 15;
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_NORMAL;
+ m_builtArgs.fontStyle = DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_NORMAL;
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL;
+ m_builtArgs.foregroundColor = Windows::UI::Colors::Black;
+ m_builtArgs.rawPixelsPerViewPixel = 1;
+ m_builtArgs.readingDirection = DWRITE_READING_DIRECTION::DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+ m_builtArgs.textLocale = ref new String(L"en-US");
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_NO_WRAP;
+ m_builtArgs.fontCollection = nullptr;
+ m_builtArgs.textAlignment = DWRITE_TEXT_ALIGNMENT_LEADING;
+}
+
+void DirectWriteRenderArgBuilder::SetFontFamily(FontFamily^ fontFamily)
+{
+ String^ resultFontFamily;
+
+ // try to get the FontFamily property first.
+ auto controlFontFamily = fontFamily;
+ if ((controlFontFamily != nullptr) && !controlFontFamily->Source->IsEmpty())
+ {
+ // if there's something in the font family, use it.
+ resultFontFamily = controlFontFamily->Source;
+ }
+
+ // if nothing was in the font family, try the XAML default value.
+ if (resultFontFamily->IsEmpty() && (controlFontFamily != nullptr))
+ {
+ auto xamlDefault = FontFamily::XamlAutoFontFamily;
+ if ((xamlDefault != nullptr) && !xamlDefault->Source->IsEmpty())
+ {
+ resultFontFamily = xamlDefault->Source;
+ }
+ }
+
+ // if the xaml default failed for some reason, hardcode to Segoe UI as last fallback.
+ if (resultFontFamily->IsEmpty())
+ {
+ resultFontFamily = L"Segoe UI";
+ }
+
+ m_builtArgs.fontFamily = resultFontFamily;
+ BuildFontCollection(resultFontFamily);
+}
+
+void DirectWriteRenderArgBuilder::SetText(Platform::String^ text)
+{
+ m_builtArgs.text = text;
+}
+
+void DirectWriteRenderArgBuilder::SetTextLocale(Platform::String^ textLocale)
+{
+ if (Language::IsWellFormed(textLocale))
+ {
+ m_builtArgs.textLocale = textLocale;
+ }
+ else
+ {
+ // default to en-US.
+ m_builtArgs.textLocale = ref new String(L"en-US");
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetForegroundBrush(Brush^ brush)
+{
+ auto solidColorBrush = dynamic_cast(brush);
+ if (solidColorBrush != nullptr)
+ {
+ m_builtArgs.foregroundColor = solidColorBrush->Color;
+ }
+ else
+ {
+ m_builtArgs.foregroundColor = Colors::Black;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetFontStyle(FontStyle fontStyle)
+{
+ switch (fontStyle)
+ {
+ case FontStyle::Normal: __fallthrough;
+ default:
+ m_builtArgs.fontStyle = DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_NORMAL;
+ break;
+ case FontStyle::Italic:
+ m_builtArgs.fontStyle = DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_ITALIC;
+ break;
+ case FontStyle::Oblique:
+ m_builtArgs.fontStyle = DWRITE_FONT_STYLE::DWRITE_FONT_STYLE_OBLIQUE;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetFontStretch(FontStretch fontStretch)
+{
+ switch (fontStretch)
+ {
+ case FontStretch::Normal: __fallthrough;
+ default:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_NORMAL;
+ break;
+ case FontStretch::Condensed:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_CONDENSED;
+ break;
+ case FontStretch::Expanded:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_EXPANDED;
+ break;
+ case FontStretch::ExtraCondensed:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_EXTRA_CONDENSED;
+ break;
+ case FontStretch::ExtraExpanded:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_EXTRA_EXPANDED;
+ break;
+ case FontStretch::SemiCondensed:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_SEMI_CONDENSED;
+ break;
+ case FontStretch::SemiExpanded:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_SEMI_EXPANDED;
+ break;
+ case FontStretch::UltraCondensed:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_ULTRA_CONDENSED;
+ break;
+ case FontStretch::UltraExpanded:
+ m_builtArgs.fontStretch = DWRITE_FONT_STRETCH::DWRITE_FONT_STRETCH_ULTRA_EXPANDED;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetTextReadingDirection(DirectWriteReadingDirection textReadingDirection)
+{
+ switch (textReadingDirection)
+ {
+ case DirectWriteReadingDirection::TopToBottom: __fallthrough;
+ default:
+ m_builtArgs.readingDirection = DWRITE_READING_DIRECTION::DWRITE_READING_DIRECTION_TOP_TO_BOTTOM;
+ break;
+ case DirectWriteReadingDirection::LeftToRight:
+ m_builtArgs.readingDirection = DWRITE_READING_DIRECTION::DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
+ break;
+ case DirectWriteReadingDirection::RightToLeft:
+ m_builtArgs.readingDirection = DWRITE_READING_DIRECTION::DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
+ break;
+ case DirectWriteReadingDirection::BottomToTop:
+ m_builtArgs.readingDirection = DWRITE_READING_DIRECTION::DWRITE_READING_DIRECTION_BOTTOM_TO_TOP;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetFlowDirection(FlowDirection flowDirection)
+{
+ switch (flowDirection)
+ {
+ case FlowDirection::LeftToRight: __fallthrough;
+ default:
+ m_builtArgs.flowDirection = DWRITE_FLOW_DIRECTION::DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT;
+ break;
+ case FlowDirection::RightToLeft:
+ m_builtArgs.flowDirection = DWRITE_FLOW_DIRECTION::DWRITE_FLOW_DIRECTION_RIGHT_TO_LEFT;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetFontWeight(FontWeight fontWeight)
+{
+ auto weight = fontWeight.Weight;
+ if (weight == FontWeights::Black.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_BLACK;
+ }
+ else if (weight == FontWeights::Bold.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_BOLD;
+ }
+ else if (weight == FontWeights::ExtraBlack.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_EXTRA_BLACK;
+ }
+ else if (weight == FontWeights::ExtraBold.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_EXTRA_BOLD;
+ }
+ else if (weight == FontWeights::ExtraLight.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_EXTRA_LIGHT;
+ }
+ else if (weight == FontWeights::Light.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_LIGHT;
+ }
+ else if (weight == FontWeights::SemiBold.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_SEMI_BOLD;
+ }
+ else if (weight == FontWeights::SemiLight.Weight)
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_SEMI_LIGHT;
+ }
+ else
+ {
+ m_builtArgs.fontWeight = DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetTextWrapping(DirectWriteWordWrapping textWrapping)
+{
+ switch (textWrapping)
+ {
+ case DirectWriteWordWrapping::NoWrap:
+ default:
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_NO_WRAP;
+ break;
+ case DirectWriteWordWrapping::Wrap:
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_WRAP;
+ break;
+ case DirectWriteWordWrapping::WholeWord:
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_WHOLE_WORD;
+ break;
+ case DirectWriteWordWrapping::EmergencyBreak:
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_EMERGENCY_BREAK;
+ break;
+ case DirectWriteWordWrapping::Character:
+ m_builtArgs.textWrapping = DWRITE_WORD_WRAPPING::DWRITE_WORD_WRAPPING_CHARACTER;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetTextAlignment(DirectWriteTextAlignment textAlignment)
+{
+ switch (textAlignment)
+ {
+ case DirectWriteTextAlignment::Leading:
+ default:
+ m_builtArgs.textAlignment = DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_LEADING;
+ break;
+ case DirectWriteTextAlignment::Trailing:
+ m_builtArgs.textAlignment = DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_TRAILING;
+ break;
+ case DirectWriteTextAlignment::Center:
+ m_builtArgs.textAlignment = DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_CENTER;
+ break;
+ case DirectWriteTextAlignment::Justified:
+ m_builtArgs.textAlignment = DWRITE_TEXT_ALIGNMENT::DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
+ break;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetFontSize(double fontSize)
+{
+ m_builtArgs.fontSize = static_cast(fontSize);
+ if (m_builtArgs.fontSize <= 0)
+ {
+ m_builtArgs.fontSize = 15.0f;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetDPI(double rawPixelsPerViewPixel)
+{
+ m_builtArgs.rawPixelsPerViewPixel = static_cast(rawPixelsPerViewPixel);
+ if (m_builtArgs.rawPixelsPerViewPixel <= 0)
+ {
+ m_builtArgs.rawPixelsPerViewPixel = 1.0f;
+ }
+}
+
+void DirectWriteRenderArgBuilder::SetAvailableWidth(float availableWidth)
+{
+ m_builtArgs.availableWidth = availableWidth;
+}
+
+void DirectWriteRenderArgBuilder::SetAvailableHeight(float availableHeight)
+{
+ m_builtArgs.availableHeight = availableHeight;
+}
+
+DirectWriteTextRenderArgs& DirectWriteRenderArgBuilder::BuildRenderArgs()
+{
+ return m_builtArgs;
+}
+
+void DirectWriteRenderArgBuilder::BuildFontCollection(Platform::String^ fontFamily)
+{
+ // default arg is system font collection, what we're looking for is if we're trying to
+ // find a local custom ttf file.
+ if (DirectWriteFontCollectionLoader::HasCustomFontFamily(fontFamily))
+ {
+ auto resourceManager = DirectWriteResourceManager::GetInstance();
+ auto dwriteFactory = resourceManager->GetDirectWriteFactoryNoRef();
+ DirectWriteUniversalPackageFontData parseData = {};
+ DirectWriteFontCollectionLoader::ParseXamlFontFamily(fontFamily, parseData);
+ auto customLoader = DirectWriteFontCollectionLoader::GetInstance();
+
+ // the key is a void* meaning the size is actual size.
+ auto fontFamilyString = fontFamily->Data();
+ auto fontFamilySize = fontFamily->Length() * sizeof(wchar_t);
+ dwriteFactory->CreateCustomFontCollection(customLoader.get(), fontFamilyString, static_cast(fontFamilySize), m_builtArgs.fontCollection.put());
+
+ // set font family to the parsed font family.
+ m_builtArgs.fontFamily = ref new String(parseData.customFontName.data(), static_cast(parseData.customFontName.size()));
+ }
+ else
+ {
+ // else assume it's a system font for now. We could do a lookup, but that would actually slow things down.
+ m_builtArgs.fontCollection = nullptr;
+ }
+}
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.h
new file mode 100644
index 00000000000..d9c50eac95a
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteRenderArgBuilder.h
@@ -0,0 +1,156 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+public enum class DirectWriteReadingDirection : int
+{
+ LeftToRight,
+ RightToLeft,
+ TopToBottom,
+ BottomToTop
+};
+
+public enum class DirectWriteTextAlignment : int
+{
+ Leading,
+ Trailing,
+ Center,
+ Justified
+};
+
+public enum class DirectWriteWordWrapping : int
+{
+ Wrap,
+ NoWrap,
+ EmergencyBreak,
+ WholeWord,
+ Character
+};
+
+///
+/// These are arguments which are used to render the DWrite string.
+///
+struct DirectWriteTextRenderArgs
+{
+ Platform::String^ fontFamily;
+ Platform::String^ text;
+ Platform::String^ textLocale;
+ Windows::UI::Color foregroundColor;
+ DWRITE_FONT_STYLE fontStyle;
+ DWRITE_FONT_STRETCH fontStretch;
+ DWRITE_READING_DIRECTION readingDirection;
+ DWRITE_FLOW_DIRECTION flowDirection;
+ DWRITE_FONT_WEIGHT fontWeight;
+ DWRITE_WORD_WRAPPING textWrapping;
+ DWRITE_TEXT_ALIGNMENT textAlignment;
+ float fontSize;
+ float rawPixelsPerViewPixel;
+ float availableWidth;
+ float availableHeight;
+ winrt::com_ptr fontCollection;
+};
+
+///
+/// This class translates input from the XAML world into a DirectWriteTextRenderArgs struct
+/// meant to be used with the DWrite world. If the user passes invalid values in, it attempts
+/// to correct by setting them back to a known default value. This is because in case the user
+/// is using the text block from C# (most users are expected to do this), a crash ultimately
+/// just gives them a "something went wrong and a native exception was thrown" which is not
+/// super helpful. Recovery will at least render something that looks incorrect on the screen.
+///
+class DirectWriteRenderArgBuilder
+{
+public:
+ DirectWriteRenderArgBuilder();
+
+ ///
+ /// The font family, by default Segoe UI
+ ///
+ void SetFontFamily(Windows::UI::Xaml::Media::FontFamily^ fontFamily);
+
+ ///
+ /// The text to render, empty string by default.
+ ///
+ void SetText(Platform::String^ text);
+
+ ///
+ /// The text locale for DWrite, en-US by default.
+ ///
+ void SetTextLocale(Platform::String^ textLocale);
+
+ ///
+ /// The foreground brush, Black by default
+ ///
+ void SetForegroundBrush(Windows::UI::Xaml::Media::Brush^ brush);
+
+ ///
+ /// The font style, Normal by default
+ ///
+ void SetFontStyle(Windows::UI::Text::FontStyle fontStyle);
+
+ ///
+ /// The font stretch, normal by default
+ ///
+ void SetFontStretch(Windows::UI::Text::FontStretch fontStretch);
+
+ ///
+ /// The text reading direction, top to bottom by default
+ ///
+ void SetTextReadingDirection(DirectWriteReadingDirection textReadingDirection);
+
+ ///
+ /// The flow direction, LeftToRight by default
+ ///
+ void SetFlowDirection(Windows::UI::Xaml::FlowDirection flowDirection);
+
+ ///
+ /// The font weight, Normal by default
+ ///
+ void SetFontWeight(Windows::UI::Text::FontWeight fontWeight);
+
+ ///
+ /// The font size, 15 by default.
+ ///
+ void SetFontSize(double fontSize);
+
+ ///
+ /// The DPI to render at, 1 by default
+ ///
+ void SetDPI(double rawPixelsPerViewPixel);
+
+ ///
+ /// The available width to render at
+ ///
+ void SetAvailableWidth(float availableWidth);
+
+ ///
+ /// The available height to render at.
+ ///
+ void SetAvailableHeight(float availableHeight);
+
+ ///
+ /// The text wrap mode, None by default.
+ ///
+ void SetTextWrapping(DirectWriteWordWrapping textWrapping);
+
+ ///
+ /// The text alignment mode, Leading by default.
+ ///
+ void SetTextAlignment(DirectWriteTextAlignment textAlignment);
+
+
+ ///
+ /// The render arguments.
+ ///
+ DirectWriteTextRenderArgs& BuildRenderArgs();
+
+private:
+ void BuildFontCollection(Platform::String^ fontFamily);
+ DirectWriteTextRenderArgs m_builtArgs = {};
+};
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.cpp
new file mode 100644
index 00000000000..ec64171b096
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.cpp
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
+#include "DirectWriteFontCollectionLoader.h"
+#include "DirectWriteResourceManager.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+std::unique_ptr DirectWriteResourceManager::s_instance;
+
+DirectWriteResourceManager::DirectWriteResourceManager()
+{
+}
+
+DirectWriteResourceManager::~DirectWriteResourceManager()
+{
+}
+
+IDWriteFactory* DirectWriteResourceManager::GetDirectWriteFactoryNoRef()
+{
+ winrt::check_hresult(InitializeDeviceResources());
+ return m_dwriteFactory.get();
+}
+
+ID3D11Device* DirectWriteResourceManager::GetD3dDeviceNoRef()
+{
+ winrt::check_hresult(InitializeDeviceResources());
+ return m_d3dDevice.get();
+}
+
+ID2D1DeviceContext* DirectWriteResourceManager::GetD2dDCNoRef()
+{
+ winrt::check_hresult(InitializeDeviceResources());
+ return m_d2dContext.get();
+}
+
+IDXGIDevice* DirectWriteResourceManager::GetDXGIDeviceNoRef()
+{
+ winrt::check_hresult(InitializeDeviceResources());
+ return m_dxgiDevice.get();
+}
+
+HRESULT DirectWriteResourceManager::RebuildDeviceResources()
+{
+ m_deviceResourcesInitialized = false;
+ return InitializeDeviceResources();
+}
+
+HRESULT DirectWriteResourceManager::InitializeDeviceResources()
+{
+ if (!m_deviceResourcesInitialized)
+ {
+ UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+ D3D_FEATURE_LEVEL supportedFeatureLevel;
+
+ m_d3dDevice = nullptr;
+ m_d2dDevice = nullptr;
+ m_dwriteFactory = nullptr;
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1
+ };
+
+ HRESULT hr = D3D11CreateDevice(
+ nullptr, // Specify nullptr to use the default adapter.
+ D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver.
+ 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
+ creationFlags, // Set debug and Direct2D compatibility flags.
+ featureLevels, // List of feature levels this app can support.
+ ARRAYSIZE(featureLevels),
+ D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
+ m_d3dDevice.put(), // Returns the Direct3D device created.
+ &supportedFeatureLevel,
+ nullptr
+ );
+
+ // log failures on the initial creation
+ if (FAILED(hr))
+ {
+ // If the initialization fails, fall back to the WARP device.
+ winrt::check_hresult(D3D11CreateDevice(
+ nullptr,
+ D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device.
+ 0,
+ creationFlags,
+ featureLevels,
+ ARRAYSIZE(featureLevels),
+ D3D11_SDK_VERSION,
+ m_d3dDevice.put(),
+ &supportedFeatureLevel,
+ nullptr
+ ));
+ }
+
+ // Get the Direct3D 11.1 API device.
+ m_d3dDevice.as(m_dxgiDevice);
+ winrt::check_hresult(D2D1CreateDevice(m_dxgiDevice.get(), nullptr, m_d2dDevice.put()));
+
+ winrt::check_hresult(m_d2dDevice->CreateDeviceContext(
+ D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
+ m_d2dContext.put()
+ ));
+
+ winrt::check_hresult(DWriteCreateFactory(
+ DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast(m_dwriteFactory.put())
+ ));
+
+ auto customLoader = DirectWriteFontCollectionLoader::GetInstance();
+ m_dwriteFactory->RegisterFontCollectionLoader(customLoader.get());
+
+ m_deviceResourcesInitialized = true;
+ }
+
+ return S_OK;
+}
+
+DirectWriteResourceManager* DirectWriteResourceManager::GetInstance()
+{
+ if (s_instance == nullptr)
+ {
+ s_instance.reset(new DirectWriteResourceManager());
+ }
+
+ return s_instance.get();
+}
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.h
new file mode 100644
index 00000000000..1e1cd02ccff
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteResourceManager.h
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+///
+/// This manages D3D/DWrite resources and prevents reinitialization.
+///
+class DirectWriteResourceManager
+{
+public:
+ DirectWriteResourceManager();
+ virtual ~DirectWriteResourceManager();
+
+ ///
+ /// This is a singleton to prevent reintializing D3D
+ ///
+ static DirectWriteResourceManager* GetInstance();
+
+ ///
+ /// The DWrite Factory, caller doesn't take a reference.
+ ///
+ IDWriteFactory* GetDirectWriteFactoryNoRef();
+
+ ///
+ /// The D3D Device, caller doesn't take a reference.
+ ///
+ ID3D11Device* GetD3dDeviceNoRef();
+
+ ///
+ /// The D2D Device, caller doesn't take a reference.
+ ///
+ ID2D1DeviceContext* GetD2dDCNoRef();
+
+ ///
+ /// The DXGI Device, caller doesn't take a reference.
+ ///
+ IDXGIDevice* GetDXGIDeviceNoRef();
+
+ ///
+ /// Initializes the device resources.
+ ///
+ HRESULT InitializeDeviceResources();
+
+ ///
+ /// Reinitializes the device resources.
+ ///
+ HRESULT RebuildDeviceResources();
+
+private:
+ winrt::com_ptr m_dwriteFactory;
+ winrt::com_ptr m_d3dDevice;
+ winrt::com_ptr m_d2dDevice;
+ winrt::com_ptr m_d2dContext;
+ winrt::com_ptr m_dxgiDevice;
+
+ static std::unique_ptr s_instance;
+ bool m_deviceResourcesInitialized = false;
+};
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.cpp
new file mode 100644
index 00000000000..03da823d147
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.cpp
@@ -0,0 +1,367 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
+#include "DirectWriteTextBlock.h"
+#include
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Collections;
+using namespace Windows::Graphics::Display;
+using namespace Windows::UI::Xaml;
+using namespace Windows::UI::Xaml::Controls;
+using namespace Windows::UI::Xaml::Data;
+using namespace Windows::UI::Xaml::Documents;
+using namespace Windows::UI::Xaml::Input;
+using namespace Windows::UI::Xaml::Interop;
+using namespace Windows::UI::Xaml::Media;
+using namespace Windows::UI::Xaml::Media::Imaging;
+using namespace Windows::UI::ViewManagement;
+
+DependencyProperty^ DirectWriteTextBlock::m_textProperty = DependencyProperty::Register(
+ L"Text",
+ Platform::String::typeid,
+ DirectWriteTextBlock::typeid,
+ ref new PropertyMetadata(L"", ref new PropertyChangedCallback(&DirectWriteTextBlock::OnDependencyPropertyChanged)));
+
+DependencyProperty^ DirectWriteTextBlock::m_textLocaleProperty = DependencyProperty::Register(
+ L"TextLocale",
+ Platform::String::typeid,
+ DirectWriteTextBlock::typeid,
+ ref new PropertyMetadata(L"en-US", ref new PropertyChangedCallback(&DirectWriteTextBlock::OnDependencyPropertyChanged)));
+
+DependencyProperty^ DirectWriteTextBlock::m_textReadingDirectionProperty = DependencyProperty::Register(
+ L"TextReadingDirection",
+ DirectWriteReadingDirection::typeid,
+ DirectWriteTextBlock::typeid,
+ ref new PropertyMetadata(ref new Platform::Box(DirectWriteReadingDirection::TopToBottom), ref new PropertyChangedCallback(&DirectWriteTextBlock::OnDependencyPropertyChanged)));
+
+DependencyProperty^ DirectWriteTextBlock::m_textWrapProperty = DependencyProperty::Register(
+ L"TextWrap",
+ DirectWriteWordWrapping::typeid,
+ DirectWriteTextBlock::typeid,
+ ref new PropertyMetadata(ref new Platform::Box(DirectWriteWordWrapping::NoWrap), ref new PropertyChangedCallback(&DirectWriteTextBlock::OnDependencyPropertyChanged)));
+
+DependencyProperty^ DirectWriteTextBlock::m_textAlignmentProperty = DependencyProperty::Register(
+ L"TextAlign",
+ DirectWriteTextAlignment::typeid,
+ DirectWriteTextBlock::typeid,
+ ref new PropertyMetadata(ref new Platform::Box(DirectWriteTextAlignment::Leading), ref new PropertyChangedCallback(&DirectWriteTextBlock::OnDependencyPropertyChanged)));
+
+
+DirectWriteTextBlock::DirectWriteTextBlock()
+{
+ DefaultStyleKey = "Microsoft.Toolkit.Uwp.UI.Controls.WinRT.DirectWriteTextBlock";
+
+ m_displayInfo = DisplayInformation::GetForCurrentView();
+ m_dpiChangedToken = m_displayInfo->DpiChanged += ref new TypedEventHandler(this, &DirectWriteTextBlock::OnDpiChanged);
+
+ m_accessibilitySettings = ref new AccessibilitySettings();
+ m_highContrastChangedToken = m_accessibilitySettings->HighContrastChanged += ref new TypedEventHandler(this, &DirectWriteTextBlock::OnHighContrastSettingsChanged);
+ m_isHighContrast = m_accessibilitySettings->HighContrast;
+
+#define REGISTER_INHERITED_PROPERTY_CALLBACK(token, inheritedProperty) \
+ token = RegisterPropertyChangedCallback(inheritedProperty, ref new DependencyPropertyChangedCallback(&DirectWriteTextBlock::OnInheritedDependencyPropertyChanged))
+
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_flowDirectionChangedToken, FlowDirectionProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_foregroundChangedToken, ForegroundProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_fontSizeChangedToken, FontSizeProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_fontFamilyChangedToken, FontFamilyProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_fontStretchChangedToken, FontStretchProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_fontStyleChangedToken, FontStyleProperty);
+ REGISTER_INHERITED_PROPERTY_CALLBACK(m_fontWeightChangedToken, FontWeightProperty);
+#undef REGISTER_INHERITED_PROPERTY_CALLBACK
+}
+
+DirectWriteTextBlock::~DirectWriteTextBlock()
+{
+ Close();
+}
+
+void DirectWriteTextBlock::OnApplyTemplate()
+{
+ // make XAML apply the template first
+ __super::OnApplyTemplate();
+
+ auto maybeImage = dynamic_cast(GetTemplateChild(L"Image"));
+ if (!maybeImage)
+ {
+ winrt::throw_hresult(E_NOT_VALID_STATE);
+ }
+
+ // this border is essentially just used to emulate the XAML text high contrast background.
+ // the consumer can use it to set background to the text block, but normally, it should just be
+ // left null.
+ auto maybeBorder = dynamic_cast(GetTemplateChild(L"TextBackground"));
+ if (!maybeBorder)
+ {
+ winrt::throw_hresult(E_NOT_VALID_STATE);
+ }
+
+ m_image = maybeImage;
+ m_textBackground = maybeBorder;
+}
+
+Size DirectWriteTextBlock::MeasureOverride(Size availableSize)
+{
+ UpdateTextBrushesForHighContrast();
+ auto displayInfo = DisplayInformation::GetForCurrentView();
+ DirectWriteRenderArgBuilder builder;
+ builder.SetAvailableHeight(availableSize.Height);
+ builder.SetAvailableWidth(availableSize.Width);
+ builder.SetDPI(displayInfo->RawPixelsPerViewPixel);
+ builder.SetFlowDirection(FlowDirection);
+ builder.SetFontFamily(FontFamily);
+ builder.SetFontSize(FontSize);
+ builder.SetFontStretch(FontStretch);
+ builder.SetFontStyle(FontStyle);
+ builder.SetFontWeight(FontWeight);
+ builder.SetForegroundBrush(m_textForegroundBrush);
+ builder.SetText(Text);
+ builder.SetTextLocale(TextLocale);
+ builder.SetTextReadingDirection(TextReadingDirection);
+ builder.SetTextWrapping(TextWrap);
+ builder.SetTextAlignment(TextAlign);
+
+ auto args = builder.BuildRenderArgs();
+ UpdateElementsForHighContrast();
+
+ auto resultSize = RenderText(args);
+
+ // call __super::Measure after we've already set the source to the new image.
+ __super::MeasureOverride(availableSize);
+ return resultSize;
+}
+
+void DirectWriteTextBlock::UpdateTextBrushesForHighContrast()
+{
+ if (m_isHighContrast)
+ {
+ // XAML High Contrast TextBlock behavior emulation: XAML on high contrast basically sets
+ // a background to the TextBlock in order to get text to always appear in High Contrast.
+ // To emulate this, we basically look up the applicable text brushes from the system
+ // resource dictionary and override any foreground/background the user may have set like
+ // standard textblock would.
+
+ auto resources = Application::Current->Resources;
+ auto highContrastForeground = static_cast(resources->Lookup(L"SystemColorWindowTextColor"));
+ auto highContrastBackground = static_cast(resources->Lookup(L"SystemColorWindowColor"));
+ m_textForegroundBrush = ref new SolidColorBrush(highContrastForeground);
+ m_textBackgroundBrush = ref new SolidColorBrush(highContrastBackground);
+ }
+ else
+ {
+ m_textForegroundBrush = this->Foreground;
+ m_textBackgroundBrush = this->Background;
+ }
+}
+
+void DirectWriteTextBlock::UpdateElementsForHighContrast()
+{
+ if (m_textBackground)
+ {
+ m_textBackground->Background = m_textBackgroundBrush;
+ }
+}
+
+void DirectWriteTextBlock::Close()
+{
+
+#define UNREGISTER_INHERITED_PROPERTY_CALLBACK(token, inheritedProperty) \
+ if (token != 0) \
+ { \
+ UnregisterPropertyChangedCallback(inheritedProperty, token); \
+ token = 0; \
+ }
+
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_flowDirectionChangedToken, FlowDirectionProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_foregroundChangedToken, ForegroundProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_fontSizeChangedToken, FontSizeProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_fontFamilyChangedToken, FontFamilyProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_fontStretchChangedToken, FontStretchProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_fontStyleChangedToken, FontStyleProperty);
+ UNREGISTER_INHERITED_PROPERTY_CALLBACK(m_fontWeightChangedToken, FontWeightProperty);
+
+ if (m_dpiChangedToken.Value != 0)
+ {
+ m_displayInfo->DpiChanged -= m_dpiChangedToken;
+ m_dpiChangedToken = {};
+ }
+
+ if (m_highContrastChangedToken.Value != 0)
+ {
+ m_accessibilitySettings->HighContrastChanged -= m_highContrastChangedToken;
+ m_highContrastChangedToken = {};
+ }
+
+#undef UNREGISTER_INHERITED_PROPERTY_CALLBACK
+}
+
+Size DirectWriteTextBlock::RenderText(DirectWriteTextRenderArgs const& args)
+{
+ if ((m_image == nullptr) || args.text->IsEmpty())
+ {
+ return Size(0.0f, 0.0f);
+ }
+
+ auto resourceManager = DirectWriteResourceManager::GetInstance();
+ auto scale = args.rawPixelsPerViewPixel;
+ auto scaledFontSize = args.fontSize * scale;
+ auto dwriteFactory = resourceManager->GetDirectWriteFactoryNoRef();
+
+ winrt::com_ptr textFormat;
+ winrt::check_hresult(dwriteFactory->CreateTextFormat(
+ args.fontFamily->Data(),
+ args.fontCollection.get(),
+ args.fontWeight,
+ args.fontStyle,
+ args.fontStretch,
+ scaledFontSize,
+ args.textLocale->Data(),
+ textFormat.put()));
+
+ textFormat->SetWordWrapping(args.textWrapping);
+
+ // Trying to set readingDirection + FlowDirection to LEFT_TO_RIGHT will result in
+ // a failed HRESULT From DWRITE. Since the defaults work fine for horizontal, only
+ // set these values for text orientation = vertical.
+ auto textReadingDirection = this->TextReadingDirection;
+ if (textReadingDirection != DirectWriteReadingDirection::LeftToRight)
+ {
+ textFormat->SetReadingDirection(args.readingDirection);
+ textFormat->SetFlowDirection(args.flowDirection);
+ }
+
+ textFormat->SetTextAlignment(args.textAlignment);
+
+ winrt::com_ptr textLayout;
+ winrt::check_hresult(dwriteFactory->CreateTextLayout(
+ args.text->Data(),
+ args.text->Length(),
+ textFormat.get(),
+ args.availableWidth,
+ args.availableHeight,
+ textLayout.put()));
+
+ DWRITE_TEXT_METRICS textMetrics = {};
+ winrt::check_hresult(textLayout->GetMetrics(&textMetrics));
+
+ // the image has to be scaled since we're manually handling DPI changes.
+ auto sisWidth = static_cast(std::ceil(textMetrics.width * scale));
+ auto sisHeight = static_cast(std::ceil(textMetrics.height * scale));
+ auto imageSource = ref new SurfaceImageSource(sisWidth, sisHeight);
+ auto sisUnknown = reinterpret_cast(imageSource);
+ winrt::com_ptr sisNative;
+ sisUnknown->QueryInterface(__uuidof(ISurfaceImageSourceNative), sisNative.put_void());
+ sisNative->SetDevice(resourceManager->GetDXGIDeviceNoRef());
+
+ winrt::com_ptr surface;
+ RECT updateRect = { 0, 0, static_cast(sisWidth), static_cast(sisHeight) };
+ POINT offset = { 0, 0 };
+ m_lastDrawError = sisNative->BeginDraw(updateRect, surface.put(), &offset);
+ if (SUCCEEDED(m_lastDrawError))
+ {
+ auto d2dContext = resourceManager->GetD2dDCNoRef();
+
+ // set the translation to the section of the bitmap that we want to render.
+ auto translate = D2D1::Matrix3x2F::Translation(static_cast(offset.x), static_cast(offset.y));
+ d2dContext->SetTransform(translate);
+
+ // this basically ensures the text background is transparent.
+ D2D1_BITMAP_PROPERTIES1 bitmapProperties =
+ {
+ { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
+ 96.f * scale,
+ 96.f * scale,
+ D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW
+ };
+
+ winrt::com_ptr bitmap;
+ winrt::check_hresult(d2dContext->CreateBitmapFromDxgiSurface(
+ surface.get(),
+ &bitmapProperties,
+ bitmap.put()));
+
+ d2dContext->SetTarget(bitmap.get());
+ d2dContext->BeginDraw();
+ d2dContext->Clear();
+
+ winrt::com_ptr brush;
+ auto color = args.foregroundColor;
+ D2D1_COLOR_F d2dColor = D2D1::ColorF(
+ static_cast(color.R) / 255.0f,
+ static_cast(color.G) / 255.0f,
+ static_cast(color.B) / 255.0f,
+ static_cast(color.A) / 255.0f);
+ winrt::check_hresult(d2dContext->CreateSolidColorBrush(d2dColor, brush.put()));
+
+ d2dContext->DrawText(
+ args.text->Data(),
+ args.text->Length(),
+ textFormat.get(),
+ D2D1::RectF(0, 0, static_cast(sisWidth), static_cast(sisHeight)),
+ brush.get(),
+ D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
+
+ HRESULT d2dEndDrawResult = d2dContext->EndDraw();
+ sisNative->EndDraw();
+
+ if (d2dEndDrawResult == D2DERR_RECREATE_TARGET)
+ {
+ winrt::check_hresult(resourceManager->RebuildDeviceResources());
+ }
+
+ m_image->Source = imageSource;
+ m_drawRetries = 0;
+
+ // XAML will rescale, so we divide by scale here.
+ return Size{ static_cast(sisWidth / scale), static_cast(sisHeight / scale) };
+ }
+ else if (m_drawRetries == 0)
+ {
+ // D2D draw can fail for multiple reasons where rebuilding the D3D device might be necessary.
+ winrt::check_hresult(resourceManager->RebuildDeviceResources());
+ m_drawRetries++;
+ return RenderText(args);
+ }
+ else
+ {
+ // if we fail to draw 2x a retry, just bail.
+ return Size(0.0f, 0.0f);
+ }
+}
+
+void DirectWriteTextBlock::OnDependencyPropertyChanged(_In_ DependencyObject^ d, _In_ DependencyPropertyChangedEventArgs^ /* e */)
+{
+ auto textBlockInstance = dynamic_cast(d);
+ if (textBlockInstance)
+ {
+ textBlockInstance->InvalidateMeasure();
+ }
+}
+
+void DirectWriteTextBlock::OnInheritedDependencyPropertyChanged(_In_ DependencyObject^ d, _In_ DependencyProperty^ /* e */)
+{
+ auto textBlockInstance = dynamic_cast(d);
+ if (textBlockInstance)
+ {
+ textBlockInstance->InvalidateMeasure();
+ }
+}
+
+void DirectWriteTextBlock::OnDpiChanged(_In_ DisplayInformation^ /* displayInfo */, _In_ Object^ /* obj */)
+{
+ InvalidateMeasure();
+}
+
+void DirectWriteTextBlock::OnHighContrastSettingsChanged(_In_ AccessibilitySettings^ accessibilitySettings, _In_ Object^ /* obj */)
+{
+ m_isHighContrast = accessibilitySettings->HighContrast;
+ InvalidateMeasure();
+}
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.h
new file mode 100644
index 00000000000..0476948e15b
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteTextBlock.h
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+#include "DirectWriteResourceManager.h"
+#include "DirectWriteRenderArgBuilder.h"
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+#define DEFINE_XAML_DEPENDENCY_PROPERTY(type, name, membername) \
+ public: \
+ property type name \
+ { \
+ type get() \
+ { \
+ return (type)(GetValue(membername)); \
+ } \
+ void set(type value) \
+ { \
+ SetValue(membername, value); \
+ } \
+ } \
+ static property Windows::UI::Xaml::DependencyProperty^ name ## Property \
+ { \
+ Windows::UI::Xaml::DependencyProperty^ get() \
+ { \
+ return membername; \
+ } \
+ } \
+ private: \
+ static Windows::UI::Xaml::DependencyProperty^ membername; \
+ public:
+
+#define DEFINE_XAML_DEPENDENCY_PROPERTY_VALUE_TYPE(type, name, membername) \
+ public: \
+ property type name \
+ { \
+ type get() \
+ { \
+ auto boxedType = dynamic_cast^>(GetValue(membername)); \
+ if (boxedType != nullptr) \
+ { \
+ return boxedType->Value; \
+ } \
+ else \
+ { \
+ return static_cast((int)(GetValue(membername))); \
+ } \
+ } \
+ void set(type value) \
+ { \
+ SetValue(membername, ref new Platform::Box(value)); \
+ } \
+ } \
+ static property Windows::UI::Xaml::DependencyProperty^ name ## Property \
+ { \
+ Windows::UI::Xaml::DependencyProperty^ get() \
+ { \
+ return membername; \
+ } \
+ } \
+ private: \
+ static Windows::UI::Xaml::DependencyProperty^ membername; \
+ public:
+
+///
+/// This is a text block which uses DirectWrite to draw text onto a bitmap image, allowing the user to orient text vertically for
+/// East Asian languages and to support text rendering modes which aren't supported by XAML yet, but are supported by DirectWrite.
+///
+/// Parts of this are built using C++/WinRT and will require the 1803 Windows SDK to build and use at minumum.
+///
+///
+/// The current XAML code gen for C++/WinRT is in preview and results in a compile error so the main project class is C++/CX to get around
+/// that limitation.
+///
+/// Throwing out of this class will cause significant debuggability issues in C# consumers as they just get a "native exception was thrown."
+/// Therefore, this class will attempt to recover from poor input like setting font size = 0. If something happens like a DWrite
+/// method fails, that will throw an exception.
+///
+[Windows::Foundation::Metadata::WebHostHidden]
+public ref class DirectWriteTextBlock sealed : public Windows::UI::Xaml::Controls::Control
+{
+public:
+ DirectWriteTextBlock();
+ virtual ~DirectWriteTextBlock();
+
+ ///
+ /// The text to render
+ ///
+ DEFINE_XAML_DEPENDENCY_PROPERTY(Platform::String^, Text, m_textProperty);
+
+ ///
+ /// The locale of the text to show
+ ///
+ DEFINE_XAML_DEPENDENCY_PROPERTY(Platform::String^, TextLocale, m_textLocaleProperty);
+
+ ///
+ /// The reading direction of the text.
+ ///
+ DEFINE_XAML_DEPENDENCY_PROPERTY_VALUE_TYPE(DirectWriteReadingDirection, TextReadingDirection, m_textReadingDirectionProperty);
+
+ ///
+ /// How the text is wrapped. To Wrap text, just set the Height or Width of this control.
+ ///
+ DEFINE_XAML_DEPENDENCY_PROPERTY_VALUE_TYPE(DirectWriteWordWrapping, TextWrap, m_textWrapProperty);
+
+ ///
+ /// The direct write based alignment of the text. This is agnostic of XAML and only supports DirectWrite values.
+ ///
+ DEFINE_XAML_DEPENDENCY_PROPERTY_VALUE_TYPE(DirectWriteTextAlignment, TextAlign, m_textAlignmentProperty);
+
+protected:
+ // These are the methods we're overriding from IFrameworkElementOverrides.
+ void OnApplyTemplate() override;
+ Windows::Foundation::Size MeasureOverride(Windows::Foundation::Size availableSize) override;
+
+private:
+ static void OnDependencyPropertyChanged(_In_ Windows::UI::Xaml::DependencyObject^ d, _In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ e);
+ static void OnInheritedDependencyPropertyChanged(_In_ Windows::UI::Xaml::DependencyObject^ d, _In_ Windows::UI::Xaml::DependencyProperty^ e);
+ void OnDpiChanged(_In_ Windows::Graphics::Display::DisplayInformation^ displayInfo, _In_ Platform::Object^ obj);
+ void OnHighContrastSettingsChanged(_In_ Windows::UI::ViewManagement::AccessibilitySettings^ accessibilitySettings, _In_ Platform::Object^ obj);
+ Windows::Foundation::Size RenderText(DirectWriteTextRenderArgs const& args);
+ void Close();
+ void UpdateTextBrushesForHighContrast();
+ void UpdateElementsForHighContrast();
+
+ Windows::Foundation::EventRegistrationToken m_dpiChangedToken = {};
+ Windows::Foundation::EventRegistrationToken m_highContrastChangedToken = {};
+
+ long long m_foregroundChangedToken = 0;
+ long long m_fontSizeChangedToken = 0;
+ long long m_fontFamilyChangedToken = 0;
+ long long m_flowDirectionChangedToken = 0;
+ long long m_fontStretchChangedToken = 0;
+ long long m_fontWeightChangedToken = 0;
+ long long m_fontStyleChangedToken = 0;
+
+ Windows::UI::ViewManagement::AccessibilitySettings^ m_accessibilitySettings;
+ Windows::UI::Xaml::Controls::Image^ m_image;
+ Windows::UI::Xaml::Controls::Border^ m_textBackground;
+ Windows::UI::Xaml::Media::Brush^ m_textForegroundBrush;
+ Windows::UI::Xaml::Media::Brush^ m_textBackgroundBrush;
+ Windows::Graphics::Display::DisplayInformation^ m_displayInfo;
+ bool m_isHighContrast = false;
+ HRESULT m_lastDrawError = S_OK;
+ unsigned int m_drawRetries = 0;
+};
+
+END_NAMESPACE_CONTROLS_WINRT
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteUniversalPackageFontData.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteUniversalPackageFontData.h
new file mode 100644
index 00000000000..ae48537259d
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/DirectWriteTextBlock/DirectWriteUniversalPackageFontData.h
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+BEGIN_NAMESPACE_CONTROLS_WINRT
+
+struct DirectWriteUniversalPackageFontData
+{
+ std::wstring packageFontFilePath;
+ std::wstring customFontName;
+};
+
+END_NAMESPACE_CONTROLS_WINRT
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.targets b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.targets
new file mode 100644
index 00000000000..0144421e37e
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.targets
@@ -0,0 +1,20 @@
+
+
+
+ x86
+ $(Platform)
+
+
+
+ Microsoft.Toolkit.Uwp.UI.Controls.WinRT.dll
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\..\Include;%(AdditionalIncludeDirectories)
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj
new file mode 100644
index 00000000000..82b0f762ee6
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj
@@ -0,0 +1,272 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {d4c7ac54-826a-4412-8461-a7c7fd86534b}
+ WindowsRuntimeComponent
+ Microsoft.Toolkit.Uwp.UI.Controls.WinRT
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0.17763.0
+ 10.0.17763.0
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v141
+
+
+ DynamicLibrary
+ true
+ v141
+
+
+ DynamicLibrary
+ true
+ v141
+
+
+ DynamicLibrary
+ false
+ true
+ v141
+
+
+ DynamicLibrary
+ false
+ true
+ v141
+
+
+ DynamicLibrary
+ false
+ true
+ v141
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ ..\Toolkit.ruleset
+ false
+
+
+ false
+ ..\Toolkit.ruleset
+ true
+
+
+ false
+ ..\Toolkit.ruleset
+ false
+
+
+ false
+ ..\Toolkit.ruleset
+ true
+
+
+ false
+ ..\Toolkit.ruleset
+ false
+
+
+ false
+ ..\Toolkit.ruleset
+ true
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ true
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ true
+ true
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ false
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ true
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ false
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+ stdcpplatest
+ true
+ Level4
+ true
+
+
+ Console
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj.filters b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj.filters
new file mode 100644
index 00000000000..fb0f85196ea
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj.filters
@@ -0,0 +1,57 @@
+
+
+
+
+ 843e9b69-b3be-436a-8063-712dd68c8c9e
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {68b61fb4-e30f-4e13-a90a-d600506ffe67}
+
+
+ {100341cc-ce8e-481d-a525-78892e08dcd8}
+
+
+
+
+
+ DirectWriteTextBlock
+
+
+ DirectWriteTextBlock
+
+
+ DirectWriteTextBlock
+
+
+ UniversalWindowsAppPackageFontLoader
+
+
+ UniversalWindowsAppPackageFontLoader
+
+
+
+
+
+ DirectWriteTextBlock
+
+
+ DirectWriteTextBlock
+
+
+ DirectWriteTextBlock
+
+
+ UniversalWindowsAppPackageFontLoader
+
+
+ UniversalWindowsAppPackageFontLoader
+
+
+ UniversalWindowsAppPackageFontLoader
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Themes/Generic.xaml b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Themes/Generic.xaml
new file mode 100644
index 00000000000..8469728a44d
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/Themes/Generic.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.cpp b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.cpp
new file mode 100644
index 00000000000..1fc2c700b11
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.cpp
@@ -0,0 +1,5 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "pch.h"
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.h b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.h
new file mode 100644
index 00000000000..1df4bb844b5
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.WinRT/pch.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+// these are c++/winrt default includes : https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/author-coclasses
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define BEGIN_NAMESPACE_CONTROLS_WINRT namespace Microsoft { namespace Toolkit { namespace Uwp { namespace UI { namespace Controls { namespace WinRT {
+#define END_NAMESPACE_CONTROLS_WINRT } } } } } }
+
+#include "DirectWriteTextBlock\DirectWriteTextBlock.h"
+
+// it would be nice to run Code Analysis on this project, but the Code Analyzer crashes due to the generated XAML files and apparently can't find pch.h
\ No newline at end of file
diff --git a/Windows Community Toolkit.sln b/Windows Community Toolkit.sln
index afe96a143b7..756b45fb284 100644
--- a/Windows Community Toolkit.sln
+++ b/Windows Community Toolkit.sln
@@ -93,6 +93,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.UI.Co
{3DD8AA7C-3569-4E51-992F-0C2257E8878E} = {3DD8AA7C-3569-4E51-992F-0C2257E8878E}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Toolkit.Uwp.UI.Controls.WinRT", "Microsoft.Toolkit.Uwp.UI.Controls.WinRT\Microsoft.Toolkit.Uwp.UI.Controls.WinRT.vcxproj", "{D4C7AC54-826A-4412-8461-A7C7FD86534B}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{982cc826-aacd-4855-9075-430bb6ce40a9}*SharedItemsImports = 13
@@ -659,6 +661,28 @@ Global
{D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x64.Build.0 = Release|Any CPU
{D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x86.ActiveCfg = Release|Any CPU
{D4D78CBA-B238-4794-89A0-4F1A2D8FEA97}.Release|x86.Build.0 = Release|Any CPU
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|ARM.ActiveCfg = Debug|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|ARM.Build.0 = Debug|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|x64.ActiveCfg = Debug|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|x64.Build.0 = Debug|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|x86.ActiveCfg = Debug|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Debug|x86.Build.0 = Debug|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|Any CPU.ActiveCfg = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|Any CPU.Build.0 = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|ARM.ActiveCfg = Release|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|ARM.Build.0 = Release|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|x64.ActiveCfg = Release|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|x64.Build.0 = Release|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|x86.ActiveCfg = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Native|x86.Build.0 = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|Any CPU.ActiveCfg = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|ARM.ActiveCfg = Release|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|ARM.Build.0 = Release|ARM
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|x64.ActiveCfg = Release|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|x64.Build.0 = Release|x64
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|x86.ActiveCfg = Release|Win32
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -682,6 +706,7 @@ Global
{262BB7CE-EF42-4BF7-B90C-107E6CBB57FF} = {096ECFD7-7035-4487-9C87-81DCE9389620}
{A122EA02-4DE7-413D-BFBF-AF7DFC668DD6} = {B30036C4-D514-4E5B-A323-587A061772CE}
{D4D78CBA-B238-4794-89A0-4F1A2D8FEA97} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
+ {D4C7AC54-826A-4412-8461-A7C7FD86534B} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5403B0C4-F244-4F73-A35C-FE664D0F4345}
diff --git a/build/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.nuspec b/build/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.nuspec
new file mode 100644
index 00000000000..ec11aee18d8
--- /dev/null
+++ b/build/Microsoft.Toolkit.Uwp.UI.Controls.WinRT.nuspec
@@ -0,0 +1,56 @@
+
+
+
+ Microsoft.Toolkit.Uwp.UI.Controls.WinRT
+ $version$
+ Windows Community Toolkit WinRT Controls
+ Microsoft.Toolkit
+ Microsoft.Toolkit
+ https://raw.githubusercontent.com/windows-toolkit/WindowsCommunityToolkit/master/build/nuget.png
+ https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/license.md
+ https://github.com/windows-toolkit/WindowsCommunityToolkit
+ true
+ This library provides WinRT XAML templated controls. It is part of the Windows Community Toolkit.
+ v5.0 release https://github.com/Microsoft/WindowsCommunityToolkit/releases
+ (c) .NET Foundation and Contributors. All rights reserved.
+ UWP Toolkit Windows Controls DirectWriteTextBlock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file