Windows fonts work
This commit is contained in:
parent
c24361f026
commit
bdf3675a4c
7 changed files with 357 additions and 3 deletions
|
|
@ -130,7 +130,9 @@ if((NOT EMSCRIPTEN) AND (GRAPHICS_BACKEND STREQUAL "Vulkan"))
|
|||
endif()
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND sources "windowsinstall/app.rc")
|
||||
list(APPEND sources
|
||||
"src/WindowsFontData/CustomFontSetManager.cpp"
|
||||
"windowsinstall/app.rc")
|
||||
endif()
|
||||
|
||||
# Get libraries
|
||||
|
|
@ -289,6 +291,10 @@ endif()
|
|||
|
||||
target_link_libraries(infinipaint zstd::libzstd_static)
|
||||
|
||||
if((NOT EMSCRIPTEN) AND WIN32)
|
||||
target_link_libraries(infinipaint dwrite)
|
||||
endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
add_subdirectory(deps/datachannel-wasm EXCLUDE_FROM_ALL)
|
||||
target_link_libraries(infinipaint datachannel-wasm)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@
|
|||
#include <include/ports/SkFontMgr_directory.h>
|
||||
#elif _WIN32
|
||||
#include <include/ports/SkTypeface_win.h>
|
||||
#include "WindowsFontData/CustomFontSetManager.h"
|
||||
|
||||
DWriteCustomFontSets::CustomFontSetManager fontSetManagerWindows;
|
||||
|
||||
#else
|
||||
#include <include/ports/SkFontMgr_fontconfig.h>
|
||||
#include <include/ports/SkFontScanner_FreeType.h>
|
||||
|
|
@ -15,21 +19,29 @@
|
|||
#endif
|
||||
|
||||
#include <src/base/SkUTF.h>
|
||||
#include <filesystem>
|
||||
|
||||
FontData::FontData()
|
||||
{
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
localFontMgr = SkFontMgr_New_Custom_Empty();
|
||||
defaultFontMgr = SkFontMgr_New_Custom_Directory("data/fonts");
|
||||
#elif _WIN32
|
||||
localFontMgr = SkFontMgr_New_DirectWrite();
|
||||
defaultFontMgr = SkFontMgr_New_DirectWrite();
|
||||
std::vector<std::wstring> fontPaths;
|
||||
for(const std::filesystem::path& dirEntry : std::filesystem::recursive_directory_iterator(std::filesystem::path(L"data\\fonts")))
|
||||
fontPaths.emplace_back(dirEntry.wstring());
|
||||
fontSetManagerWindows.CreateFontSetUsingLocalFontFiles(fontPaths);
|
||||
fontSetManagerWindows.CreateFontCollectionFromFontSet();
|
||||
|
||||
IDWriteFactory* fac = fontSetManagerWindows.IDWriteFactory5_IsAvailable() ? fontSetManagerWindows.m_dwriteFactory5.Get() : fontSetManagerWindows.m_dwriteFactory3.Get();
|
||||
defaultFontMgr = SkFontMgr_New_DirectWrite(fac, fontSetManagerWindows.m_customFontCollection.Get());
|
||||
#else
|
||||
localFontMgr = SkFontMgr_New_FontConfig(nullptr, SkFontScanner_Make_FreeType());
|
||||
defaultFontMgr = SkFontMgr_New_Custom_Directory("data/fonts");
|
||||
#endif
|
||||
|
||||
|
||||
map["Roboto"] = defaultFontMgr->makeFromFile("data/fonts/Roboto-variable.ttf");
|
||||
|
||||
collection = sk_make_sp<skia::textlayout::FontCollection>();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include <Eigen/Dense>
|
||||
#include <modules/skparagraph/include/FontCollection.h>
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
struct FontData {
|
||||
|
|
|
|||
203
src/WindowsFontData/CustomFontSetManager.cpp
Normal file
203
src/WindowsFontData/CustomFontSetManager.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#pragma once
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
// Removed unnecessary functions. Is a sample from:
|
||||
// https://github.com/microsoft/Windows-classic-samples/tree/main
|
||||
|
||||
#include "CustomFontSetManager.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace DWriteCustomFontSets
|
||||
{
|
||||
|
||||
//**********************************************************************
|
||||
//
|
||||
// Constructors, destructors
|
||||
//
|
||||
//**********************************************************************
|
||||
|
||||
CustomFontSetManager::CustomFontSetManager()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
// IDWriteFactory3 supports APIs available in any Windows 10 version (build 10240 or later).
|
||||
DX::ThrowIfFailed(
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &m_dwriteFactory3)
|
||||
);
|
||||
|
||||
#ifndef FORCE_TH1_IMPLEMENTATION
|
||||
// IDWriteFactory5 supports APIs available in Windows 10 Creators Update (preview build 15021 or later).
|
||||
hr = m_dwriteFactory3.As(&m_dwriteFactory5);
|
||||
if (hr == E_NOINTERFACE)
|
||||
{
|
||||
// Let this go. Later, if we might use the interface, we'll branch gracefully.
|
||||
}
|
||||
else
|
||||
{
|
||||
DX::ThrowIfFailed(hr);
|
||||
}
|
||||
#endif // !FORCE_TH1_IMPLEMENTATION
|
||||
|
||||
} // end CustomFontSetManager::CustomFontSetManager()
|
||||
|
||||
|
||||
//**********************************************************************
|
||||
//
|
||||
// Method for checking API availability.
|
||||
//
|
||||
//**********************************************************************
|
||||
|
||||
bool CustomFontSetManager::IDWriteFactory5_IsAvailable()
|
||||
{
|
||||
return m_dwriteFactory5 != nullptr;
|
||||
}
|
||||
|
||||
|
||||
void CustomFontSetManager::CreateFontCollectionFromFontSet() {
|
||||
if(IDWriteFactory5_IsAvailable())
|
||||
m_dwriteFactory5->CreateFontCollectionFromFontSet(m_customFontSet.Get(), m_customFontCollection.GetAddressOf());
|
||||
else
|
||||
m_dwriteFactory3->CreateFontCollectionFromFontSet(m_customFontSet.Get(), m_customFontCollection.GetAddressOf());
|
||||
}
|
||||
|
||||
//**********************************************************************
|
||||
//
|
||||
// Methods for the creating a font set under the various scenarios.
|
||||
//
|
||||
//**********************************************************************
|
||||
|
||||
void CustomFontSetManager::CreateFontSetUsingLocalFontFiles(const std::vector<std::wstring>& selectedFilePathNames)
|
||||
{
|
||||
// Requires any version of Windows 10.
|
||||
|
||||
// Creates a custom font set for font files at paths in local storage. If a file is
|
||||
// an OpenType collection file, which contains multiple fonts, all of the fonts will
|
||||
// be added to the collection.
|
||||
//
|
||||
// If running on Windows 10 Creators Update (preview build 15021 or later), the
|
||||
// IDWriteFontSetBuilder1::AddFontFile method will be used. This method handles all of
|
||||
// the fonts in an OpenType collection file in a single call, and it also supports
|
||||
// OpenType variable fonts, which can be realized as many different font faces -- all
|
||||
// named instances in the variable font will be added in a single call. This method is
|
||||
// recommended when available.
|
||||
//
|
||||
// If running on earlier Windows 10 versions, the method used will be
|
||||
// IDWriteFontSetBuilder::AddFontFaceReference. This does not support OpenType variable
|
||||
// fonts, and also requires that a font file first be analyzed to determine whether it
|
||||
// is an OpenType collection file, in which case each font must be handled in a separate
|
||||
// call.
|
||||
//
|
||||
// If one of the input path names is not a font file, it will be ignored.
|
||||
//
|
||||
// When creating a custom font set with font files that are not assumed to be known by
|
||||
// the app, DWrite will need to extract some basic font properties, such as names,
|
||||
// directly from the font files. This will result in a little extra I/O overhead.
|
||||
|
||||
// Check if IDWriteFontSetBuilder1 will be available (we're running on preview build 15021 or later)
|
||||
if (m_dwriteFactory5 != nullptr)
|
||||
{
|
||||
// We'll need an IDWriteFontFile for each font file to be added to the font set.
|
||||
// We won't assume every file is a font file in a supported format; if not, we'll
|
||||
// ignore the file.
|
||||
|
||||
// Get the font set builder -- IDWriteFontSetBuilder1.
|
||||
ComPtr<IDWriteFontSetBuilder1> fontSetBuilder;
|
||||
DX::ThrowIfFailed(
|
||||
m_dwriteFactory5->CreateFontSetBuilder(&fontSetBuilder)
|
||||
);
|
||||
|
||||
// Loop over the file paths.
|
||||
for (auto& filePath : selectedFilePathNames)
|
||||
{
|
||||
ComPtr<IDWriteFontFile> fontFile;
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_dwriteFactory5->CreateFontFileReference(filePath.c_str(), /* filetime */ nullptr, &fontFile)
|
||||
);
|
||||
|
||||
// Add to the font set builder. If the file is a collection, all of the fonts will
|
||||
// get added. If the file is not a supported font file, the call will fail; we'll
|
||||
// check for that and ignore.
|
||||
HRESULT hr = fontSetBuilder->AddFontFile(fontFile.Get());
|
||||
if ((hr != DWRITE_E_FILEFORMAT) && (hr != DWRITE_E_FILENOTFOUND) && (hr != DWRITE_E_FILEACCESS))
|
||||
{
|
||||
// Ignore file format or access errors.
|
||||
DX::ThrowIfFailed(hr);
|
||||
}
|
||||
} // for loop
|
||||
|
||||
// Now create the custom font set.
|
||||
DX::ThrowIfFailed(
|
||||
fontSetBuilder->CreateFontSet(&m_customFontSet)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're limited to APIs and functionality available on earlier Windows 10 versions, prior
|
||||
// to the Windows 10 Creators Update (preview build 15021).
|
||||
//
|
||||
// Also, we'll need an IDWriteFontFaceReference for each font to be added to the font set.
|
||||
// If a file is an OpenType collection, it may contain multiple fonts. For that reason,
|
||||
// we'll need to analyze the file to get the count of fonts, and then provide an index
|
||||
// when creating each font face reference.
|
||||
|
||||
// Get the font set builder - IDWriteFontSetBuilder.
|
||||
ComPtr<IDWriteFontSetBuilder> fontSetBuilder;
|
||||
DX::ThrowIfFailed(
|
||||
m_dwriteFactory3->CreateFontSetBuilder(&fontSetBuilder)
|
||||
);
|
||||
|
||||
// Loop over the file paths.
|
||||
for (auto& filePath : selectedFilePathNames)
|
||||
{
|
||||
ComPtr<IDWriteFontFile> fontFile;
|
||||
DX::ThrowIfFailed(
|
||||
m_dwriteFactory3->CreateFontFileReference(filePath.c_str(), /* filetime */ nullptr, &fontFile)
|
||||
);
|
||||
|
||||
// Confirm the file is a supported font file and get the collection face count.
|
||||
BOOL isSupported;
|
||||
DWRITE_FONT_FILE_TYPE fileType;
|
||||
UINT32 numberOfFonts;
|
||||
DX::ThrowIfFailed(
|
||||
fontFile->Analyze(&isSupported, &fileType, /* face type */ nullptr, &numberOfFonts)
|
||||
);
|
||||
if (!isSupported)
|
||||
continue;
|
||||
|
||||
// For each font within the font file, get a font face reference and add to the builder.
|
||||
for (UINT32 fontIndex = 0; fontIndex < numberOfFonts; fontIndex++)
|
||||
{
|
||||
ComPtr<IDWriteFontFaceReference> fontFaceReference;
|
||||
DX::ThrowIfFailed(
|
||||
m_dwriteFactory3->CreateFontFaceReference(fontFile.Get(), fontIndex, DWRITE_FONT_SIMULATIONS_NONE, &fontFaceReference)
|
||||
);
|
||||
|
||||
// If fonts were assumed known, we could set custom properties, and would do that here.
|
||||
// But these are not assumed known, so we'll leave it to DirectWrite to read properties
|
||||
// directly out of the font files.
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
fontSetBuilder->AddFontFaceReference(fontFaceReference.Get())
|
||||
);
|
||||
} // for loop -- over fonts with font file
|
||||
} // for loop -- over font files
|
||||
|
||||
// Now create the custom font set
|
||||
DX::ThrowIfFailed(
|
||||
fontSetBuilder->CreateFontSet(&m_customFontSet)
|
||||
);
|
||||
|
||||
} // end if (IDWriteFactory5_IsAvailable())
|
||||
} // end CustomFontSetManager::CreateFontSetUsingLocalFontFiles()
|
||||
} // namespace DWriteCustomFontSets
|
||||
40
src/WindowsFontData/CustomFontSetManager.h
Normal file
40
src/WindowsFontData/CustomFontSetManager.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
// Removed unnecessary functions. Is a sample from:
|
||||
// https://github.com/microsoft/Windows-classic-samples/tree/main
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DXHelper.h"
|
||||
|
||||
namespace DWriteCustomFontSets
|
||||
{
|
||||
class CustomFontSetManager
|
||||
{
|
||||
public:
|
||||
CustomFontSetManager();
|
||||
|
||||
// Method for checking API availability
|
||||
bool IDWriteFactory5_IsAvailable();
|
||||
|
||||
// Methods for creating font sets under the different scenarios.
|
||||
void CreateFontSetUsingLocalFontFiles(const std::vector<std::wstring>& selectedFilePathNames);
|
||||
|
||||
void CreateFontCollectionFromFontSet();
|
||||
|
||||
Microsoft::WRL::ComPtr<IDWriteFontSet> m_customFontSet;
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory3> m_dwriteFactory3; // Available on all Windows 10 versions (build 10240 and later).
|
||||
Microsoft::WRL::ComPtr<IDWriteFactory5> m_dwriteFactory5; // Available on Windows 10 Creators Update (preview build 15021 or later).
|
||||
Microsoft::WRL::ComPtr<IDWriteFontCollection1> m_customFontCollection;
|
||||
}; // class CustomFontSetManager
|
||||
} // namespace DWriteCustomFontSets
|
||||
47
src/WindowsFontData/DXHelper.h
Normal file
47
src/WindowsFontData/DXHelper.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// THROW_SYSTEM_ERROR is used to differentiate Win32 versus WinRT implementation for the error handling
|
||||
// defined here. Define THROW_SYSTEM_ERROR in stdafx.h if this is being used in a Win32 project, but not
|
||||
// if it's being used in a WinRT project.
|
||||
|
||||
|
||||
namespace DX
|
||||
{
|
||||
#ifdef THROW_SYSTEM_ERROR // Win32
|
||||
inline std::system_error CreateDXException(HRESULT hr)
|
||||
{
|
||||
return std::system_error(std::error_code(hr, std::system_category()));
|
||||
}
|
||||
#else // Throw WinRT exception.
|
||||
inline Platform::Exception^ CreateDXException(HRESULT hr)
|
||||
{
|
||||
return Platform::Exception::CreateException(hr);
|
||||
}
|
||||
#endif // THROW_SYSTEM_ERROR
|
||||
|
||||
|
||||
// Convert DirectX error codes to exceptions.
|
||||
inline void ThrowIfFailed(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Set a breakpoint on this line to catch Win32 API errors.
|
||||
throw CreateDXException(hr);
|
||||
}
|
||||
}
|
||||
|
||||
} // DX namespace
|
||||
44
src/WindowsFontData/stdafx.h
Normal file
44
src/WindowsFontData/stdafx.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
|
||||
#pragma once
|
||||
|
||||
// Define used to determine Win32 rather than WinRT implementation. This is used within DXHelper.h.
|
||||
// Don't define in a WinRT project.
|
||||
#ifndef THROW_SYSTEM_ERROR
|
||||
#define THROW_SYSTEM_ERROR
|
||||
#endif // !THROW_SYSTEM_ERROR
|
||||
|
||||
|
||||
// Define used to force code paths that would be available on Windows 10 versions prior to the
|
||||
// Creators Update (preview build 15021). Only define if you want to force those code paths.
|
||||
//#ifndef FORCE_TH1_IMPLEMENTATION
|
||||
//#define FORCE_TH1_IMPLEMENTATION
|
||||
//#endif // !FORCE_TH1_IMPLEMENTATION
|
||||
|
||||
#include <dwrite_3.h>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <map> // std::map, used in CommandLineArgs
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wrl/client.h> // Microsoft::WRL, for ComPtr; could also use ATL CComPtr or raw pointers, but not std::shared_ptr
|
||||
|
||||
|
||||
// The project linker settings have been modified to list dwrite.lib as an additional dependency. (Note: this needs to be
|
||||
// done for all configurations and platforms.) Alternatively, the following pragma can be used to declare the dependency:
|
||||
// #pragma comment(lib, "dwrite")
|
||||
Loading…
Add table
Add a link
Reference in a new issue