diff --git a/build/libass/config.h b/build/libass/config.h
index fda7ef5cf..d2fc12117 100644
--- a/build/libass/config.h
+++ b/build/libass/config.h
@@ -3,3 +3,4 @@
#define CONFIG_ASM 1
#define CONFIG_RASTERIZER 1
+#define CONFIG_DIRECTWRITE 1
diff --git a/build/libass/libass.vcxproj b/build/libass/libass.vcxproj
index df487b6b8..61408f354 100644
--- a/build/libass/libass.vcxproj
+++ b/build/libass/libass.vcxproj
@@ -96,6 +96,7 @@
+
@@ -107,4 +108,4 @@
{fb8e8d19-a4d6-4181-943c-282075f49b41}
-
+
\ No newline at end of file
diff --git a/build/libass/libass.vcxproj.filters b/build/libass/libass.vcxproj.filters
index 2ef6efedf..db35379ba 100644
--- a/build/libass/libass.vcxproj.filters
+++ b/build/libass/libass.vcxproj.filters
@@ -19,9 +19,6 @@
-
- Assembly Files
-
Assembly Files
@@ -49,6 +46,9 @@
Assembly Files
+
+ Assembly Files
+
@@ -87,22 +87,13 @@
Header Files
-
+
Header Files
-
+
Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
-
+
Header Files
@@ -158,5 +149,8 @@
Source Files
+
+ Source Files
+
-
+
\ No newline at end of file
diff --git a/src/libass_gdi_fontselect.cpp b/src/libass_gdi_fontselect.cpp
new file mode 100644
index 000000000..3623968e5
--- /dev/null
+++ b/src/libass_gdi_fontselect.cpp
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, Thomas Goyne
+//
+// Permission to use, copy, modify, and distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+//
+// Aegisub Project http://www.aegisub.org/
+
+extern "C" {
+#include "ass_fontselect.h"
+}
+
+#undef inline
+
+#include
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include
+
+namespace {
+class GdiFont {
+ HFONT font;
+ std::shared_ptr dc;
+
+ size_t size = 0;
+ std::unique_ptr font_data;
+
+public:
+ GdiFont(HFONT font, std::shared_ptr dc) : font(font), dc(dc) { }
+ ~GdiFont() { DeleteObject(font); }
+
+ size_t GetData(unsigned char *data, size_t offset, size_t len);
+ bool CheckPostscript() { return false; }
+ bool CheckGlyph(uint32_t codepoint) { return true; }
+ void Destroy() { delete this; }
+};
+
+size_t GdiFont::GetData(unsigned char *data, size_t offset, size_t len) {
+ if (!font_data) {
+ SelectObject(dc.get(), font);
+ size = GetFontData(dc.get(), 0, 0, 0, 0);
+ if (size == GDI_ERROR)
+ return 0;
+ font_data.reset(new char[size]);
+ GetFontData(dc.get(), 0, 0, font_data.get(), size);
+ }
+
+ if (!data)
+ return size;
+ memcpy(data, font_data.get() + offset, len);
+ return len;
+}
+
+void match_fonts(ASS_Library *lib, ASS_FontProvider *provider, char *name) {
+ std::shared_ptr dc(CreateCompatibleDC(nullptr), [](HDC dc) { DeleteDC(dc); });
+
+ LOGFONTW lf{};
+ lf.lfCharSet = DEFAULT_CHARSET;
+ MultiByteToWideChar(CP_UTF8, 0, name, -1, lf.lfFaceName, LF_FACESIZE);
+ auto cb = [=](LOGFONTW const& lf) {
+ ASS_FontProviderMetaData meta{};
+ meta.weight = lf.lfWeight;
+ meta.slant = lf.lfItalic ? FONT_SLANT_ITALIC : FONT_SLANT_NONE;
+ meta.width = FONT_WIDTH_NORMAL;
+
+ meta.families= static_cast(malloc(sizeof(char *)));
+ meta.n_family = 1;
+
+ auto name = static_cast(malloc(LF_FACESIZE * 4));
+ auto len = wcsnlen(lf.lfFaceName, LF_FACESIZE);
+ auto written = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, len,
+ name, LF_FACESIZE * 4, nullptr, nullptr);
+ name[written] = 0;
+ meta.families[0] = name;
+
+ auto hfont = CreateFontIndirectW(&lf);
+ ass_font_provider_add_font(provider, &meta, nullptr, 0, new GdiFont(hfont, dc));
+ };
+ using type = decltype(cb);
+ EnumFontFamiliesEx(dc.get(), &lf, [](const LOGFONT *lf, const TEXTMETRIC *, DWORD, LPARAM lParam) -> int {
+ (*reinterpret_cast(lParam))(*lf);
+ return 1;
+ }, (LPARAM)&cb, 0);
+}
+
+template struct wrapper;
+template
+struct wrapper {
+ static R call(void *obj, Args... args) {
+ return (static_cast(obj)->*method)(args...);
+ }
+};
+}
+
+extern "C"
+ASS_FontProvider *ass_directwrite_add_provider(ASS_Library *,
+ ASS_FontSelector *selector,
+ const char *) {
+#define WRAP(method) &wrapper::call
+ static ASS_FontProviderFuncs callbacks = {
+ WRAP(GdiFont::GetData),
+ WRAP(GdiFont::CheckPostscript),
+ WRAP(GdiFont::CheckGlyph),
+ WRAP(GdiFont::Destroy),
+ nullptr, // destroy_provider
+ &match_fonts,
+ nullptr, // get_substitution
+ nullptr, // get_fallback
+ };
+ return ass_font_provider_new(selector, &callbacks, nullptr);
+}