Merge pull request 'Atlas factory' (#189) from atlas_factory into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/189 Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
@@ -32,8 +32,8 @@ jobs:
|
||||
- name: Install Dev Packages
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: >
|
||||
sudo apt update && sudo apt install -y extra-cmake-modules libwayland-dev libxkbcommon-dev xorg-dev libarchive-dev libassimp-dev ninja-build glslang-tools glslang-dev unzip zip libcurl4-openssl-dev libfreetype-dev libjpeg-turbo8-dev nasm
|
||||
&& sudo wget https://sourceforge.net/projects/bin2c/files/1.1/bin2c-1.1.zip && sudo unzip bin2c-1.1.zip && cd bin2c && sudo gcc -o bin2c bin2c.c && sudo mv bin2c /usr/bin
|
||||
sudo apt update && sudo apt install -y extra-cmake-modules libwayland-dev fonts-ubuntu libxkbcommon-dev xorg-dev libarchive-dev libassimp-dev ninja-build glslang-tools glslang-dev unzip zip libcurl4-openssl-dev libfreetype-dev libjpeg-turbo8-dev nasm
|
||||
&& sudo wget https://sourceforge.net/projects/bin2c/files/1.1/bin2c-1.1.zip && sudo unzip bin2c-1.1.zip && cd bin2c && sudo gcc -o bin2c bin2c.c && sudo mv bin2c /usr/bin && fc-cache -f -v
|
||||
|
||||
- name: Get cmake checks from cache
|
||||
uses: actions/cache@v4
|
||||
|
||||
96
.vscode/settings.json
vendored
Normal file
96
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"csetjmp": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"thread": "cpp",
|
||||
"*.inc": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"hash_set": "cpp",
|
||||
"strstream": "cpp",
|
||||
"barrier": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"charconv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"coroutine": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"source_location": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"rope": "cpp",
|
||||
"slist": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"latch": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"scoped_allocator": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"syncstream": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,24 @@ namespace OpenVulkano
|
||||
return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
|
||||
}
|
||||
|
||||
static void ToLower(std::string& str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(), [](char c) { return std::tolower(c); });
|
||||
}
|
||||
|
||||
static void ToLower(const std::string& str, char* dest)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), dest, [](char c) { return std::tolower(c); });
|
||||
}
|
||||
|
||||
static std::string ToLower(const std::string& str)
|
||||
{
|
||||
std::string dest;
|
||||
dest.resize(str.size());
|
||||
std::transform(str.begin(), str.end(), dest.begin(), [](char c) { return std::tolower(c); });
|
||||
return dest;
|
||||
}
|
||||
|
||||
static std::pair<std::string, std::string> SplitAtLastOccurrence(const std::string& str, char splitAt)
|
||||
{
|
||||
size_t pos = str.rfind(splitAt);
|
||||
|
||||
56
openVulkanoCpp/Host/Linux/SystemFontResolver.cpp
Normal file
56
openVulkanoCpp/Host/Linux/SystemFontResolver.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Base/Utils.hpp"
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <memory>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
const std::string& SystemFontResolver::GetSystemFontPath(const std::string& fontName)
|
||||
{
|
||||
// fontName -> fontPath
|
||||
static std::map<std::string, std::string> fontFilesMapping = ReadSystemFonts();
|
||||
static std::string fallbackString;
|
||||
auto it = fontFilesMapping.find(Utils::ToLower(fontName));
|
||||
return it == fontFilesMapping.end() ? fallbackString : it->second;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SystemFontResolver::ReadSystemFonts()
|
||||
{
|
||||
std::unique_ptr<FcConfig, decltype(&FcConfigDestroy)> config(FcInitLoadConfigAndFonts(), &FcConfigDestroy);
|
||||
std::unique_ptr<FcPattern, decltype(&FcPatternDestroy)> pat(FcPatternCreate(), &FcPatternDestroy);
|
||||
std::unique_ptr<FcObjectSet, decltype(&FcObjectSetDestroy)> os(FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, NULL), &FcObjectSetDestroy);
|
||||
std::unique_ptr<FcFontSet, decltype(&FcFontSetDestroy)> fs(FcFontList(config.get(), pat.get(), os.get()), &FcFontSetDestroy);
|
||||
|
||||
if (!fs)
|
||||
{
|
||||
Logger::DATA->warn("Could not get system fonts");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> fontFilesMapping;
|
||||
for (int i = 0; i < fs->nfont; ++i)
|
||||
{
|
||||
FcPattern* font = fs->fonts[i];
|
||||
FcChar8* file;
|
||||
FcChar8* style;
|
||||
FcChar8* family;
|
||||
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch &&
|
||||
FcPatternGetString(font, FC_FAMILY, 0, &family) == FcResultMatch &&
|
||||
FcPatternGetString(font, FC_STYLE, 0, &style) == FcResultMatch)
|
||||
{
|
||||
std::string fontFull = std::string(reinterpret_cast<char*>(family)) + " " +
|
||||
std::string(reinterpret_cast<char*>(style));
|
||||
Utils::ToLower(fontFull);
|
||||
fontFilesMapping[std::move(fontFull)] = std::string(reinterpret_cast<char*>(file));
|
||||
}
|
||||
}
|
||||
return fontFilesMapping;
|
||||
}
|
||||
}
|
||||
22
openVulkanoCpp/Host/MacOS/SystemFontResolver.cpp
Normal file
22
openVulkanoCpp/Host/MacOS/SystemFontResolver.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
const std::string& SystemFontResolver::GetSystemFontPath(const std::string& fontName)
|
||||
{
|
||||
static std::string fallbackString;
|
||||
return fallbackString;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SystemFontResolver::ReadSystemFonts()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ namespace OpenVulkano
|
||||
{
|
||||
NSOperatingSystemVersion sysVersion = [NSProcessInfo processInfo].operatingSystemVersion;
|
||||
osVersion = { static_cast<int>(sysVersion.majorVersion), static_cast<int>(sysVersion.minorVersion),
|
||||
static_cast<int>(sysVersion.patchVersion), 0 };
|
||||
static_cast<int>(sysVersion.patchVersion), 0 };
|
||||
}
|
||||
return osVersion;
|
||||
}
|
||||
|
||||
22
openVulkanoCpp/Host/SystemFontResolver.hpp
Normal file
22
openVulkanoCpp/Host/SystemFontResolver.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
class SystemFontResolver
|
||||
{
|
||||
public:
|
||||
static const std::string& GetSystemFontPath(const std::string& fontName);
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::string> ReadSystemFonts();
|
||||
};
|
||||
}
|
||||
142
openVulkanoCpp/Host/Windows/SystemFontResolver.cpp
Normal file
142
openVulkanoCpp/Host/Windows/SystemFontResolver.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include "Base/Utils.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include <Windows.h>
|
||||
#include <dwrite_3.h>
|
||||
#include <filesystem>
|
||||
|
||||
#define QFR_DESCRIPTION 1
|
||||
|
||||
#pragma comment(lib, "Dwrite.lib")
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
struct DirectWriteAutoReleasable final
|
||||
{
|
||||
DirectWriteAutoReleasable() : ptr(nullptr) {}
|
||||
~DirectWriteAutoReleasable()
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
ptr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
T* operator->() { return ptr; }
|
||||
|
||||
T* ptr;
|
||||
};
|
||||
}
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
const std::string& SystemFontResolver::GetSystemFontPath(const std::string& fontName)
|
||||
{
|
||||
// font name -> filename
|
||||
static std::map<std::string, std::string> fontFileMapping = ReadSystemFonts();
|
||||
static std::string fallbackString;
|
||||
auto it = fontFileMapping.find(Utils::ToLower(fontName));
|
||||
return it == fontFileMapping.end() ? fallbackString : it->second;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SystemFontResolver::ReadSystemFonts()
|
||||
{
|
||||
DirectWriteAutoReleasable<IDWriteFactory7> dwrite;
|
||||
HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory7), (IUnknown**) &dwrite);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
Logger::DATA->error("Could not read system fonts. DWriteCreateFactory has failed. Error code {}", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
DirectWriteAutoReleasable<IDWriteFontSet> matchingFonts;
|
||||
hr = dwrite->GetSystemFontSet(&matchingFonts.ptr);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
Logger::DATA->error("Could not read system fonts. GetSystemFontSet has failed. Error code {}", hr);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> fontFileMapping;
|
||||
const UINT32 familyCount = matchingFonts->GetFontCount();
|
||||
// thank you Microsoft for function that is not even documented, but exists and it's the only function that
|
||||
// can return real font name from font filename (e.g. font filename is times.ttf that corresponds to Times New Roman)
|
||||
int(WINAPI* GetFontResourceInfoW)(wchar_t*, unsigned long*, void*, unsigned long);
|
||||
*(FARPROC*) &GetFontResourceInfoW = GetProcAddress(GetModuleHandleA("gdi32"), "GetFontResourceInfoW");
|
||||
|
||||
for (UINT32 i = 0; i < familyCount; ++i)
|
||||
{
|
||||
DirectWriteAutoReleasable<IDWriteFontFaceReference> faceRef;
|
||||
hr = matchingFonts->GetFontFaceReference(i, &faceRef.ptr);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DirectWriteAutoReleasable<IDWriteFontFile> file;
|
||||
hr = faceRef->GetFontFile(&file.ptr);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DirectWriteAutoReleasable<IDWriteFontFileLoader> loader;
|
||||
hr = file->GetLoader(&loader.ptr);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DirectWriteAutoReleasable<IDWriteLocalFontFileLoader> localLoader;
|
||||
hr = loader->QueryInterface(&localLoader.ptr);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const void* fileKey;
|
||||
UINT32 fileKeySize;
|
||||
hr = file->GetReferenceKey(&fileKey, &fileKeySize);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get font path
|
||||
WCHAR filePath[MAX_PATH];
|
||||
hr = localLoader->GetFilePathFromKey(fileKey, fileKeySize, filePath, MAX_PATH);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get font name
|
||||
unsigned long size = 0;
|
||||
if (!GetFontResourceInfoW(filePath, &size, NULL, QFR_DESCRIPTION))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::wstring fontName;
|
||||
fontName.resize(size);
|
||||
if (GetFontResourceInfoW(filePath, &size, fontName.data(), QFR_DESCRIPTION))
|
||||
{
|
||||
// remove null-terminated characters since size is always bigger than needed
|
||||
std::string fontNameCropped(fontName.begin(), fontName.end());
|
||||
const size_t realSize = strlen(fontNameCropped.data());
|
||||
fontNameCropped.resize(realSize);
|
||||
Utils::ToLower(fontNameCropped);
|
||||
fontFileMapping[std::move(fontNameCropped)] = std::string(filePath, filePath + wcslen(filePath));
|
||||
}
|
||||
}
|
||||
return fontFileMapping;
|
||||
}
|
||||
|
||||
}
|
||||
22
openVulkanoCpp/Host/iOS/SystemFontResolver.cpp
Normal file
22
openVulkanoCpp/Host/iOS/SystemFontResolver.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
const std::string& SystemFontResolver::GetSystemFontPath(const std::string& fontName)
|
||||
{
|
||||
static std::string fallbackString;
|
||||
return fallbackString;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> SystemFontResolver::ReadSystemFonts()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace OpenVulkano
|
||||
{
|
||||
NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion;
|
||||
osv = { static_cast<int>(osVersion.majorVersion), static_cast<int>(osVersion.minorVersion),
|
||||
static_cast<int>(osVersion.patchVersion), 0 };
|
||||
static_cast<int>(osVersion.patchVersion), 0 };
|
||||
}
|
||||
return osv;
|
||||
}
|
||||
|
||||
@@ -157,9 +157,8 @@ namespace OpenVulkano::Scene
|
||||
+ glyph.firstGlyphByteInAtlas;
|
||||
for (int row = 0; row < slot->bitmap.rows; row++)
|
||||
{
|
||||
std::memcpy(baseAddress + row * m_atlasData->GetTexture()->resolution.x,
|
||||
&slot->bitmap.buffer[(slot->bitmap.rows - 1 - row) * slot->bitmap.pitch],
|
||||
slot->bitmap.width);
|
||||
std::memcpy(baseAddress - row * m_atlasData->GetTexture()->resolution.x,
|
||||
&slot->bitmap.buffer[row * slot->bitmap.pitch], slot->bitmap.width);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace OpenVulkano::Scene
|
||||
void DeserializeMetadata(const std::span<char>& data);
|
||||
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FontAtlas>;
|
||||
|
||||
FontAtlas() = default;
|
||||
FontAtlas(const Math::Vector2ui textureResolution, const double lineHeight, const FontAtlasType atlasType,
|
||||
DataFormat dataFormat)
|
||||
|
||||
106
openVulkanoCpp/Scene/Text/FontAtlasFactory.cpp
Normal file
106
openVulkanoCpp/Scene/Text/FontAtlasFactory.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "FontAtlasFactory.hpp"
|
||||
#include "Scene/SdfFontAtlasGenerator.hpp"
|
||||
#include "Scene/BitmapFontAtlasGenerator.hpp"
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Host/ResourceLoader.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
FontAtlasFactory::FontIdentifier::FontIdentifier(const std::string& font_, const std::set<uint32_t>& charset,
|
||||
SubpixelLayout subpixelLayout_, float ptSize_,
|
||||
FontAtlasType atlasType_)
|
||||
: font(font_), subpixelLayout(subpixelLayout_), ptSize(ptSize_), atlasType(atlasType_)
|
||||
{
|
||||
std::for_each(charset.begin(), charset.end(), [&](uint32_t c) { charsetHash ^= c; });
|
||||
}
|
||||
|
||||
bool FontAtlasFactory::FontIdentifier::FontIdentifier::operator<(const FontIdentifier& other) const
|
||||
{
|
||||
return std::tie(atlasType, charsetHash, ptSize, subpixelLayout, font)
|
||||
< std::tie(other.atlasType, other.charsetHash, other.ptSize, other.subpixelLayout, other.font);
|
||||
}
|
||||
|
||||
FontAtlas::Ptr FontAtlasFactory::GetFontAtlasScalable(const std::string& fontIdentifier, bool msdf,
|
||||
const std::set<uint32_t>& charset) const
|
||||
{
|
||||
const auto& fontData = FindFont(fontIdentifier);
|
||||
if (fontData.Empty())
|
||||
{
|
||||
Logger::DATA->warn("Could not find font {}", fontIdentifier);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::set<uint32_t>& setRef = (charset.empty() ? FontAtlasGeneratorBase::LoadAllGlyphs(fontData) : charset);
|
||||
FontIdentifier id(fontIdentifier, setRef, SubpixelLayout::UNKNOWN, 0,
|
||||
msdf ? FontAtlasType::MSDF : FontAtlasType::SDF);
|
||||
|
||||
auto it = m_atlasesCache.find(id);
|
||||
if (it != m_atlasesCache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (msdf)
|
||||
{
|
||||
MsdfFontAtlasGenerator msdfGen;
|
||||
msdfGen.GenerateAtlas(fontData, setRef);
|
||||
return m_atlasesCache.insert({ id, msdfGen.GetAtlas() }).first->second;
|
||||
}
|
||||
SdfFontAtlasGenerator sdfGen;
|
||||
sdfGen.GenerateAtlas(fontData, setRef);
|
||||
return m_atlasesCache.insert({ id, sdfGen.GetAtlas() }).first->second;
|
||||
}
|
||||
|
||||
FontAtlas::Ptr FontAtlasFactory::GetFontAtlas(const std::string& fontIdentifier, float ptSize,
|
||||
SubpixelLayout subpixelLayout,
|
||||
const std::set<uint32_t>& charset) const
|
||||
{
|
||||
const auto& fontData = FindFont(fontIdentifier);
|
||||
if (fontData.Empty())
|
||||
{
|
||||
Logger::DATA->warn("Could not find font {}", fontIdentifier);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::set<uint32_t>& setRef = (charset.empty() ? FontAtlasGeneratorBase::LoadAllGlyphs(fontData) : charset);
|
||||
FontIdentifier id(fontIdentifier, setRef, subpixelLayout, ptSize,
|
||||
subpixelLayout ? FontAtlasType::BITMAP_SUBPIXEL : FontAtlasType::BITMAP);
|
||||
|
||||
auto it = m_atlasesCache.find(id);
|
||||
if (it != m_atlasesCache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
FontPixelSizeConfig cfg(ptSize);
|
||||
BitmapFontAtlasGenerator bitmapGen(cfg, subpixelLayout);
|
||||
bitmapGen.GenerateAtlas(fontData, setRef);
|
||||
return m_atlasesCache.insert({ id, bitmapGen.GetAtlas() }).first->second;
|
||||
}
|
||||
|
||||
Array<char> FontAtlasFactory::FindFont(const std::string& fontIdentifier) const
|
||||
{
|
||||
Array<char> resource = ResourceLoader::GetInstance().GetResource(fontIdentifier);
|
||||
if (resource.Empty())
|
||||
{
|
||||
if (!std::filesystem::exists(fontIdentifier))
|
||||
{
|
||||
if (!m_allowSystemFonts)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return Utils::ReadFile(SystemFontResolver::GetSystemFontPath(fontIdentifier), true);
|
||||
}
|
||||
return Utils::ReadFile(fontIdentifier);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
44
openVulkanoCpp/Scene/Text/FontAtlasFactory.hpp
Normal file
44
openVulkanoCpp/Scene/Text/FontAtlasFactory.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FontAtlas.hpp"
|
||||
#include "Scene/SubpixelLayout.hpp"
|
||||
#include "Data/Containers/Array.hpp"
|
||||
|
||||
namespace OpenVulkano::Scene
|
||||
{
|
||||
class FontAtlasFactory final
|
||||
{
|
||||
struct FontIdentifier
|
||||
{
|
||||
FontIdentifier(const std::string& font_, const std::set<uint32_t>& charset, SubpixelLayout subpixelLayout_,
|
||||
float ptSize_, FontAtlasType atlasType_);
|
||||
bool operator<(const FontIdentifier& other) const;
|
||||
|
||||
std::string font;
|
||||
uint32_t charsetHash = 0;
|
||||
SubpixelLayout subpixelLayout = SubpixelLayout::UNKNOWN;
|
||||
float ptSize = 0;
|
||||
FontAtlasType atlasType;
|
||||
};
|
||||
public:
|
||||
FontAtlasFactory(bool allowSystemFonts = true) : m_allowSystemFonts(allowSystemFonts) {}
|
||||
[[nodiscard]] FontAtlas::Ptr GetFontAtlasScalable(const std::string& fontIdentifier, bool msdf = true,
|
||||
const std::set<uint32_t>& charset = {}) const;
|
||||
[[nodiscard]] FontAtlas::Ptr GetFontAtlas(const std::string& fontIdentifier, float ptSize,
|
||||
SubpixelLayout subpixelLayout = SubpixelLayout::UNKNOWN,
|
||||
const std::set<uint32_t>& charset = {}) const;
|
||||
|
||||
private:
|
||||
Array<char> FindFont(const std::string& fontFile) const;
|
||||
|
||||
private:
|
||||
const bool m_allowSystemFonts;
|
||||
mutable std::map<FontIdentifier, FontAtlas::Ptr> m_atlasesCache;
|
||||
};
|
||||
}
|
||||
@@ -15,6 +15,17 @@ if (APPLE)
|
||||
list(FILTER SOURCES EXCLUDE REGEX "ExeAppendedZipResourceLoader")
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
find_program(LSB_RELEASE_EXEC lsb_release)
|
||||
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
|
||||
OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if (NOT ${LSB_RELEASE_ID_SHORT} STREQUAL "Ubuntu")
|
||||
list(FILTER SOURCES EXCLUDE REGEX "*Ubuntu*")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES})
|
||||
file(GLOB_RECURSE RESOURCES "${ROOT_FOLDER}/resources/*.rc" "${ROOT_FOLDER}/resources/*.h")
|
||||
list(APPEND SOURCES ${RESOURCES})
|
||||
|
||||
33
tests/Host/Linux/SystemFontsSearchTestsUbuntu.cpp
Normal file
33
tests/Host/Linux/SystemFontsSearchTestsUbuntu.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
using namespace OpenVulkano;
|
||||
|
||||
TEST_CASE("Search system fonts")
|
||||
{
|
||||
Logger::SetupLogger("", "tests.log");
|
||||
|
||||
// assume these fonts are present since they are default
|
||||
std::string path = SystemFontResolver::GetSystemFontPath("Ubuntu Regular");
|
||||
REQUIRE(path == "/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("ubuntu regular");
|
||||
REQUIRE(path == "/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("Ubuntu Mono Bold Italic");
|
||||
REQUIRE(path == "/usr/share/fonts/truetype/ubuntu/UbuntuMono-BI.ttf");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("ubuntu mono bold italic");
|
||||
REQUIRE(path == "/usr/share/fonts/truetype/ubuntu/UbuntuMono-BI.ttf");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("NON-EXISTING Font");
|
||||
REQUIRE(path.empty());
|
||||
}
|
||||
33
tests/Host/Windows/SystemFontsSearchTests.cpp
Normal file
33
tests/Host/Windows/SystemFontsSearchTests.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
#include "Base/Logger.hpp"
|
||||
#include "Host/SystemFontResolver.hpp"
|
||||
#include <filesystem>
|
||||
|
||||
#include "Scene/Text/FontAtlasFactory.hpp"
|
||||
|
||||
using namespace OpenVulkano;
|
||||
|
||||
TEST_CASE("Search system fonts")
|
||||
{
|
||||
Logger::SetupLogger("", "tests.log");
|
||||
|
||||
// assume these fonts are present since they are default
|
||||
std::filesystem::path path = SystemFontResolver::GetSystemFontPath("Arial");
|
||||
REQUIRE(path.filename() == "ARIAL.TTF");
|
||||
|
||||
// assume these fonts are present since they are default
|
||||
path = SystemFontResolver::GetSystemFontPath("Times New Roman");
|
||||
REQUIRE(path.filename() == "TIMES.TTF");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("Arial Bold Italic");
|
||||
REQUIRE(path.filename() == "ARIALBI.TTF");
|
||||
|
||||
path = SystemFontResolver::GetSystemFontPath("NON-EXISTING Font");
|
||||
REQUIRE(path.empty());
|
||||
}
|
||||
Reference in New Issue
Block a user