112 lines
2.6 KiB
C++
112 lines
2.6 KiB
C++
#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;
|
|
}
|
|
}
|