Font builder changes
This commit is contained in:
@@ -1,16 +1,9 @@
|
|||||||
#include "FontAtlasBuilder.h"
|
#include "FontAtlasBuilder.h"
|
||||||
|
|
||||||
#include "NativeHandles.h"
|
|
||||||
#include "RuntimeJson.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <wincodec.h>
|
|
||||||
#include <wrl/client.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace RenderCadenceCompositor
|
namespace RenderCadenceCompositor
|
||||||
{
|
{
|
||||||
@@ -27,45 +20,6 @@ std::string NumberText(double value)
|
|||||||
stream << value;
|
stream << value;
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ReadTextFile(const std::filesystem::path& path)
|
|
||||||
{
|
|
||||||
std::ifstream input(path, std::ios::binary);
|
|
||||||
if (!input)
|
|
||||||
return std::string();
|
|
||||||
std::ostringstream buffer;
|
|
||||||
buffer << input.rdbuf();
|
|
||||||
return buffer.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
const JsonValue* FindObjectValue(const JsonValue& object, const std::string& key)
|
|
||||||
{
|
|
||||||
return object.isObject() ? object.find(key) : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
double NumberMember(const JsonValue& object, const std::string& key, double fallback = 0.0)
|
|
||||||
{
|
|
||||||
const JsonValue* value = FindObjectValue(object, key);
|
|
||||||
return value && value->isNumber() ? value->asNumber(fallback) : fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ComThreadGuard
|
|
||||||
{
|
|
||||||
~ComThreadGuard()
|
|
||||||
{
|
|
||||||
if (initialized)
|
|
||||||
CoUninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Initialize()
|
|
||||||
{
|
|
||||||
const HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
|
||||||
initialized = SUCCEEDED(result);
|
|
||||||
return SUCCEEDED(result) || result == RPC_E_CHANGED_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool initialized = false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FontAtlasBuilder::FontAtlasBuilder(FontAtlasBuildConfig config) :
|
FontAtlasBuilder::FontAtlasBuilder(FontAtlasBuildConfig config) :
|
||||||
@@ -184,148 +138,6 @@ std::filesystem::path FontAtlasBuilder::PackageCacheDirectory(const ShaderPackag
|
|||||||
return mConfig.cacheRoot / SanitizePathToken(shaderPackage.id);
|
return mConfig.cacheRoot / SanitizePathToken(shaderPackage.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontAtlasBuilder::LoadAtlasJson(FontAtlasBuildOutput& output, std::string& error) const
|
|
||||||
{
|
|
||||||
const std::string jsonText = ReadTextFile(output.jsonPath);
|
|
||||||
if (jsonText.empty())
|
|
||||||
{
|
|
||||||
error = "Could not read font atlas json: " + output.jsonPath.string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue root;
|
|
||||||
if (!ParseJson(jsonText, root, error))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const JsonValue* metrics = FindObjectValue(root, "metrics");
|
|
||||||
if (metrics)
|
|
||||||
{
|
|
||||||
output.ascender = NumberMember(*metrics, "ascender", output.ascender);
|
|
||||||
output.descender = NumberMember(*metrics, "descender", output.descender);
|
|
||||||
output.lineHeight = NumberMember(*metrics, "lineHeight", output.lineHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
const JsonValue* glyphs = FindObjectValue(root, "glyphs");
|
|
||||||
if (!glyphs || !glyphs->isArray())
|
|
||||||
{
|
|
||||||
error = "Font atlas json has no glyph array: " + output.jsonPath.string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
output.glyphsByCodepoint.clear();
|
|
||||||
for (const JsonValue& glyphJson : glyphs->asArray())
|
|
||||||
{
|
|
||||||
if (!glyphJson.isObject())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const unsigned codepoint = static_cast<unsigned>(NumberMember(glyphJson, "unicode", 0.0));
|
|
||||||
FontAtlasBuildOutput::Glyph glyph;
|
|
||||||
glyph.advance = NumberMember(glyphJson, "advance", 0.0);
|
|
||||||
|
|
||||||
const JsonValue* planeBounds = FindObjectValue(glyphJson, "planeBounds");
|
|
||||||
const JsonValue* atlasBounds = FindObjectValue(glyphJson, "atlasBounds");
|
|
||||||
if (planeBounds && atlasBounds)
|
|
||||||
{
|
|
||||||
glyph.planeLeft = NumberMember(*planeBounds, "left", 0.0);
|
|
||||||
glyph.planeTop = NumberMember(*planeBounds, "top", 0.0);
|
|
||||||
glyph.planeRight = NumberMember(*planeBounds, "right", 0.0);
|
|
||||||
glyph.planeBottom = NumberMember(*planeBounds, "bottom", 0.0);
|
|
||||||
glyph.atlasLeft = NumberMember(*atlasBounds, "left", 0.0);
|
|
||||||
glyph.atlasTop = NumberMember(*atlasBounds, "top", 0.0);
|
|
||||||
glyph.atlasRight = NumberMember(*atlasBounds, "right", 0.0);
|
|
||||||
glyph.atlasBottom = NumberMember(*atlasBounds, "bottom", 0.0);
|
|
||||||
glyph.hasBounds = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
output.glyphsByCodepoint[codepoint] = glyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
error.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FontAtlasBuilder::LoadAtlasImage(FontAtlasBuildOutput& output, std::string& error) const
|
|
||||||
{
|
|
||||||
ComThreadGuard comGuard;
|
|
||||||
if (!comGuard.Initialize())
|
|
||||||
{
|
|
||||||
error = "Could not initialize COM for font atlas PNG loading.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IWICImagingFactory> factory;
|
|
||||||
HRESULT result = CoCreateInstance(
|
|
||||||
CLSID_WICImagingFactory,
|
|
||||||
nullptr,
|
|
||||||
CLSCTX_INPROC_SERVER,
|
|
||||||
IID_PPV_ARGS(factory.GetAddressOf()));
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not create WIC imaging factory for font atlas PNG loading.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IWICBitmapDecoder> decoder;
|
|
||||||
result = factory->CreateDecoderFromFilename(
|
|
||||||
output.imagePath.wstring().c_str(),
|
|
||||||
nullptr,
|
|
||||||
GENERIC_READ,
|
|
||||||
WICDecodeMetadataCacheOnLoad,
|
|
||||||
decoder.GetAddressOf());
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not decode font atlas PNG: " + output.imagePath.string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> frame;
|
|
||||||
result = decoder->GetFrame(0, frame.GetAddressOf());
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not read font atlas PNG frame: " + output.imagePath.string();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<IWICFormatConverter> converter;
|
|
||||||
result = factory->CreateFormatConverter(converter.GetAddressOf());
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not create WIC format converter for font atlas PNG.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = converter->Initialize(
|
|
||||||
frame.Get(),
|
|
||||||
GUID_WICPixelFormat32bppRGBA,
|
|
||||||
WICBitmapDitherTypeNone,
|
|
||||||
nullptr,
|
|
||||||
0.0,
|
|
||||||
WICBitmapPaletteTypeCustom);
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not convert font atlas PNG to RGBA.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT width = 0;
|
|
||||||
UINT height = 0;
|
|
||||||
converter->GetSize(&width, &height);
|
|
||||||
output.width = static_cast<unsigned>(width);
|
|
||||||
output.height = static_cast<unsigned>(height);
|
|
||||||
output.rgbaPixels.assign(static_cast<std::size_t>(output.width) * output.height * 4u, 0);
|
|
||||||
|
|
||||||
const UINT stride = width * 4u;
|
|
||||||
result = converter->CopyPixels(nullptr, stride, static_cast<UINT>(output.rgbaPixels.size()), output.rgbaPixels.data());
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
error = "Could not copy font atlas PNG pixels.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
error.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FontAtlasBuilder::SanitizePathToken(const std::string& value)
|
std::string FontAtlasBuilder::SanitizePathToken(const std::string& value)
|
||||||
{
|
{
|
||||||
std::string sanitized;
|
std::string sanitized;
|
||||||
@@ -339,35 +151,4 @@ std::string FontAtlasBuilder::SanitizePathToken(const std::string& value)
|
|||||||
}
|
}
|
||||||
return sanitized.empty() ? "font" : sanitized;
|
return sanitized.empty() ? "font" : sanitized;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontAtlasBuilder::RunProcess(const std::string& commandLine, const std::filesystem::path& workingDirectory, std::string& error)
|
|
||||||
{
|
|
||||||
STARTUPINFOA startupInfo = {};
|
|
||||||
PROCESS_INFORMATION processInfo = {};
|
|
||||||
startupInfo.cb = sizeof(startupInfo);
|
|
||||||
|
|
||||||
std::vector<char> mutableCommandLine(commandLine.begin(), commandLine.end());
|
|
||||||
mutableCommandLine.push_back('\0');
|
|
||||||
|
|
||||||
if (!CreateProcessA(nullptr, mutableCommandLine.data(), nullptr, nullptr, FALSE, CREATE_NO_WINDOW, nullptr, workingDirectory.string().c_str(), &startupInfo, &processInfo))
|
|
||||||
{
|
|
||||||
error = "Failed to launch msdf-atlas-gen.exe.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueHandle processHandle(processInfo.hProcess);
|
|
||||||
UniqueHandle threadHandle(processInfo.hThread);
|
|
||||||
WaitForSingleObject(processHandle.get(), INFINITE);
|
|
||||||
|
|
||||||
DWORD exitCode = 0;
|
|
||||||
GetExitCodeProcess(processHandle.get(), &exitCode);
|
|
||||||
if (exitCode != 0)
|
|
||||||
{
|
|
||||||
error = "msdf-atlas-gen.exe returned a non-zero exit code.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
error.clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
111
src/runtime/FontAtlasImageLoader.cpp
Normal file
111
src/runtime/FontAtlasImageLoader.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
#include "FontAtlasBuilder.h"
|
||||||
|
|
||||||
|
#include <wincodec.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace RenderCadenceCompositor
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct ComThreadGuard
|
||||||
|
{
|
||||||
|
~ComThreadGuard()
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialize()
|
||||||
|
{
|
||||||
|
const HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||||
|
initialized = SUCCEEDED(result);
|
||||||
|
return SUCCEEDED(result) || result == RPC_E_CHANGED_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontAtlasBuilder::LoadAtlasImage(FontAtlasBuildOutput& output, std::string& error) const
|
||||||
|
{
|
||||||
|
ComThreadGuard comGuard;
|
||||||
|
if (!comGuard.Initialize())
|
||||||
|
{
|
||||||
|
error = "Could not initialize COM for font atlas PNG loading.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IWICImagingFactory> factory;
|
||||||
|
HRESULT result = CoCreateInstance(
|
||||||
|
CLSID_WICImagingFactory,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
IID_PPV_ARGS(factory.GetAddressOf()));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not create WIC imaging factory for font atlas PNG loading.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IWICBitmapDecoder> decoder;
|
||||||
|
result = factory->CreateDecoderFromFilename(
|
||||||
|
output.imagePath.wstring().c_str(),
|
||||||
|
nullptr,
|
||||||
|
GENERIC_READ,
|
||||||
|
WICDecodeMetadataCacheOnLoad,
|
||||||
|
decoder.GetAddressOf());
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not decode font atlas PNG: " + output.imagePath.string();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> frame;
|
||||||
|
result = decoder->GetFrame(0, frame.GetAddressOf());
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not read font atlas PNG frame: " + output.imagePath.string();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IWICFormatConverter> converter;
|
||||||
|
result = factory->CreateFormatConverter(converter.GetAddressOf());
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not create WIC format converter for font atlas PNG.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = converter->Initialize(
|
||||||
|
frame.Get(),
|
||||||
|
GUID_WICPixelFormat32bppRGBA,
|
||||||
|
WICBitmapDitherTypeNone,
|
||||||
|
nullptr,
|
||||||
|
0.0,
|
||||||
|
WICBitmapPaletteTypeCustom);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not convert font atlas PNG to RGBA.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT width = 0;
|
||||||
|
UINT height = 0;
|
||||||
|
converter->GetSize(&width, &height);
|
||||||
|
output.width = static_cast<unsigned>(width);
|
||||||
|
output.height = static_cast<unsigned>(height);
|
||||||
|
output.rgbaPixels.assign(static_cast<std::size_t>(output.width) * output.height * 4u, 0);
|
||||||
|
|
||||||
|
const UINT stride = width * 4u;
|
||||||
|
result = converter->CopyPixels(nullptr, stride, static_cast<UINT>(output.rgbaPixels.size()), output.rgbaPixels.data());
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
error = "Could not copy font atlas PNG pixels.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
error.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
93
src/runtime/FontAtlasMetadata.cpp
Normal file
93
src/runtime/FontAtlasMetadata.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include "FontAtlasBuilder.h"
|
||||||
|
|
||||||
|
#include "RuntimeJson.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace RenderCadenceCompositor
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string ReadTextFile(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
std::ifstream input(path, std::ios::binary);
|
||||||
|
if (!input)
|
||||||
|
return std::string();
|
||||||
|
std::ostringstream buffer;
|
||||||
|
buffer << input.rdbuf();
|
||||||
|
return buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
const JsonValue* FindObjectValue(const JsonValue& object, const std::string& key)
|
||||||
|
{
|
||||||
|
return object.isObject() ? object.find(key) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
double NumberMember(const JsonValue& object, const std::string& key, double fallback = 0.0)
|
||||||
|
{
|
||||||
|
const JsonValue* value = FindObjectValue(object, key);
|
||||||
|
return value && value->isNumber() ? value->asNumber(fallback) : fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontAtlasBuilder::LoadAtlasJson(FontAtlasBuildOutput& output, std::string& error) const
|
||||||
|
{
|
||||||
|
const std::string jsonText = ReadTextFile(output.jsonPath);
|
||||||
|
if (jsonText.empty())
|
||||||
|
{
|
||||||
|
error = "Could not read font atlas json: " + output.jsonPath.string();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue root;
|
||||||
|
if (!ParseJson(jsonText, root, error))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const JsonValue* metrics = FindObjectValue(root, "metrics");
|
||||||
|
if (metrics)
|
||||||
|
{
|
||||||
|
output.ascender = NumberMember(*metrics, "ascender", output.ascender);
|
||||||
|
output.descender = NumberMember(*metrics, "descender", output.descender);
|
||||||
|
output.lineHeight = NumberMember(*metrics, "lineHeight", output.lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
const JsonValue* glyphs = FindObjectValue(root, "glyphs");
|
||||||
|
if (!glyphs || !glyphs->isArray())
|
||||||
|
{
|
||||||
|
error = "Font atlas json has no glyph array: " + output.jsonPath.string();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.glyphsByCodepoint.clear();
|
||||||
|
for (const JsonValue& glyphJson : glyphs->asArray())
|
||||||
|
{
|
||||||
|
if (!glyphJson.isObject())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const unsigned codepoint = static_cast<unsigned>(NumberMember(glyphJson, "unicode", 0.0));
|
||||||
|
FontAtlasBuildOutput::Glyph glyph;
|
||||||
|
glyph.advance = NumberMember(glyphJson, "advance", 0.0);
|
||||||
|
|
||||||
|
const JsonValue* planeBounds = FindObjectValue(glyphJson, "planeBounds");
|
||||||
|
const JsonValue* atlasBounds = FindObjectValue(glyphJson, "atlasBounds");
|
||||||
|
if (planeBounds && atlasBounds)
|
||||||
|
{
|
||||||
|
glyph.planeLeft = NumberMember(*planeBounds, "left", 0.0);
|
||||||
|
glyph.planeTop = NumberMember(*planeBounds, "top", 0.0);
|
||||||
|
glyph.planeRight = NumberMember(*planeBounds, "right", 0.0);
|
||||||
|
glyph.planeBottom = NumberMember(*planeBounds, "bottom", 0.0);
|
||||||
|
glyph.atlasLeft = NumberMember(*atlasBounds, "left", 0.0);
|
||||||
|
glyph.atlasTop = NumberMember(*atlasBounds, "top", 0.0);
|
||||||
|
glyph.atlasRight = NumberMember(*atlasBounds, "right", 0.0);
|
||||||
|
glyph.atlasBottom = NumberMember(*atlasBounds, "bottom", 0.0);
|
||||||
|
glyph.hasBounds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
output.glyphsByCodepoint[codepoint] = glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
error.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/runtime/FontAtlasProcess.cpp
Normal file
39
src/runtime/FontAtlasProcess.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include "FontAtlasBuilder.h"
|
||||||
|
|
||||||
|
#include "NativeHandles.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
namespace RenderCadenceCompositor
|
||||||
|
{
|
||||||
|
bool FontAtlasBuilder::RunProcess(const std::string& commandLine, const std::filesystem::path& workingDirectory, std::string& error)
|
||||||
|
{
|
||||||
|
STARTUPINFOA startupInfo = {};
|
||||||
|
PROCESS_INFORMATION processInfo = {};
|
||||||
|
startupInfo.cb = sizeof(startupInfo);
|
||||||
|
|
||||||
|
std::vector<char> mutableCommandLine(commandLine.begin(), commandLine.end());
|
||||||
|
mutableCommandLine.push_back('\0');
|
||||||
|
|
||||||
|
if (!CreateProcessA(nullptr, mutableCommandLine.data(), nullptr, nullptr, FALSE, CREATE_NO_WINDOW, nullptr, workingDirectory.string().c_str(), &startupInfo, &processInfo))
|
||||||
|
{
|
||||||
|
error = "Failed to launch msdf-atlas-gen.exe.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueHandle processHandle(processInfo.hProcess);
|
||||||
|
UniqueHandle threadHandle(processInfo.hThread);
|
||||||
|
WaitForSingleObject(processHandle.get(), INFINITE);
|
||||||
|
|
||||||
|
DWORD exitCode = 0;
|
||||||
|
GetExitCodeProcess(processHandle.get(), &exitCode);
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
error = "msdf-atlas-gen.exe returned a non-zero exit code.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
error.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,9 @@ add_video_shader_test(RenderCadenceCompositorRuntimeShaderParamsTests
|
|||||||
|
|
||||||
add_video_shader_test(RenderCadenceCompositorRuntimeLayerModelTests
|
add_video_shader_test(RenderCadenceCompositorRuntimeLayerModelTests
|
||||||
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasImageLoader.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasMetadata.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasProcess.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeLayerModel.cpp"
|
"${SRC_DIR}/runtime/RuntimeLayerModel.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeLayerReload.cpp"
|
"${SRC_DIR}/runtime/RuntimeLayerReload.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeLayerSnapshot.cpp"
|
"${SRC_DIR}/runtime/RuntimeLayerSnapshot.cpp"
|
||||||
@@ -65,6 +68,9 @@ add_video_shader_test(RuntimeStatePersistenceTests
|
|||||||
|
|
||||||
add_video_shader_test(FontAtlasBuilderTests
|
add_video_shader_test(FontAtlasBuilderTests
|
||||||
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasImageLoader.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasMetadata.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasProcess.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
||||||
"${SRC_DIR}/shader/ShaderManifestAssets.cpp"
|
"${SRC_DIR}/shader/ShaderManifestAssets.cpp"
|
||||||
"${SRC_DIR}/shader/ShaderManifestParameters.cpp"
|
"${SRC_DIR}/shader/ShaderManifestParameters.cpp"
|
||||||
@@ -75,6 +81,9 @@ add_video_shader_test(FontAtlasBuilderTests
|
|||||||
|
|
||||||
add_video_shader_test(RenderCadenceCompositorSupportedShaderCatalogTests
|
add_video_shader_test(RenderCadenceCompositorSupportedShaderCatalogTests
|
||||||
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasImageLoader.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasMetadata.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasProcess.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
||||||
"${SRC_DIR}/runtime/SupportedShaderCatalog.cpp"
|
"${SRC_DIR}/runtime/SupportedShaderCatalog.cpp"
|
||||||
"${SRC_DIR}/shader/ShaderManifestAssets.cpp"
|
"${SRC_DIR}/shader/ShaderManifestAssets.cpp"
|
||||||
@@ -89,6 +98,9 @@ add_video_shader_test(RenderCadenceCompositorRuntimeStateJsonTests
|
|||||||
"${SRC_DIR}/app/AppConfigProvider.cpp"
|
"${SRC_DIR}/app/AppConfigProvider.cpp"
|
||||||
"${SRC_DIR}/json/JsonWriter.cpp"
|
"${SRC_DIR}/json/JsonWriter.cpp"
|
||||||
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
"${SRC_DIR}/runtime/FontAtlasBuilder.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasImageLoader.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasMetadata.cpp"
|
||||||
|
"${SRC_DIR}/runtime/FontAtlasProcess.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
"${SRC_DIR}/runtime/RuntimeJson.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeLayerModel.cpp"
|
"${SRC_DIR}/runtime/RuntimeLayerModel.cpp"
|
||||||
"${SRC_DIR}/runtime/RuntimeLayerReload.cpp"
|
"${SRC_DIR}/runtime/RuntimeLayerReload.cpp"
|
||||||
|
|||||||
Reference in New Issue
Block a user