mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-22 22:45:39 +00:00
Font system refactor, use pre-rendered fonts
This commit is contained in:
313
GenerateFonts/GenerateFonts.cpp
Normal file
313
GenerateFonts/GenerateFonts.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
#include "FontFamily.h"
|
||||
#include "FontManager.h"
|
||||
#include "FontRenderer.h"
|
||||
#include "IGpFont.h"
|
||||
#include "IGpFontHandler.h"
|
||||
#include "GpAppInterface.h"
|
||||
#include "GpDriverIndex.h"
|
||||
#include "GpFontHandlerProperties.h"
|
||||
#include "GpFileSystem_Win32.h"
|
||||
#include "GpSystemServices_Win32.h"
|
||||
#include "CFileStream.h"
|
||||
|
||||
#include "PLDrivers.h"
|
||||
#include "RenderedFont.h"
|
||||
#include "RenderedFontCatalog.h"
|
||||
|
||||
#include "WindowsUnicodeToolShim.h"
|
||||
|
||||
extern "C" __declspec(dllimport) IGpFontHandler *GpDriver_CreateFontHandler_FreeType2(const GpFontHandlerProperties &properties);
|
||||
|
||||
class MemBufferStream final : public GpIOStream
|
||||
{
|
||||
public:
|
||||
size_t Read(void *bytesOut, size_t size) override;
|
||||
size_t Write(const void *bytes, size_t size) override;
|
||||
bool IsSeekable() const override;
|
||||
bool IsReadOnly() const override;
|
||||
bool IsWriteOnly() const override;
|
||||
bool SeekStart(GpUFilePos_t loc) override;
|
||||
bool SeekCurrent(GpFilePos_t loc) override;
|
||||
bool SeekEnd(GpUFilePos_t loc) override;
|
||||
GpUFilePos_t Size() const override;
|
||||
GpUFilePos_t Tell() const override;
|
||||
void Close() override;
|
||||
void Flush() override;
|
||||
|
||||
const uint8_t *GetBytes() const;
|
||||
|
||||
private:
|
||||
size_t m_writeOffset;
|
||||
std::vector<uint8_t> m_buffer;
|
||||
};
|
||||
|
||||
size_t MemBufferStream::Read(void *bytesOut, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t MemBufferStream::Write(const void *bytes, size_t size)
|
||||
{
|
||||
const uint8_t *bytesUInt8 = static_cast<const uint8_t*>(bytes);
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
if (m_writeOffset == m_buffer.size())
|
||||
m_buffer.push_back(bytesUInt8[i]);
|
||||
else
|
||||
m_buffer[m_writeOffset] = bytesUInt8[i];
|
||||
|
||||
m_writeOffset++;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool MemBufferStream::IsSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemBufferStream::IsReadOnly() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemBufferStream::IsWriteOnly() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemBufferStream::SeekStart(GpUFilePos_t loc)
|
||||
{
|
||||
m_writeOffset = static_cast<size_t>(loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemBufferStream::SeekCurrent(GpFilePos_t loc)
|
||||
{
|
||||
m_writeOffset = static_cast<size_t>(static_cast<GpFilePos_t>(m_writeOffset) + loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MemBufferStream::SeekEnd(GpUFilePos_t loc)
|
||||
{
|
||||
m_writeOffset = this->Size() - loc;
|
||||
return true;
|
||||
}
|
||||
|
||||
GpUFilePos_t MemBufferStream::Size() const
|
||||
{
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
GpUFilePos_t MemBufferStream::Tell() const
|
||||
{
|
||||
return m_writeOffset;
|
||||
}
|
||||
|
||||
void MemBufferStream::Close()
|
||||
{
|
||||
}
|
||||
|
||||
void MemBufferStream::Flush()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *MemBufferStream::GetBytes() const
|
||||
{
|
||||
return &m_buffer[0];
|
||||
}
|
||||
|
||||
struct KnownFontSpec
|
||||
{
|
||||
public:
|
||||
KnownFontSpec();
|
||||
KnownFontSpec(const char *path, int size, bool aa, PortabilityLayer::FontHacks hacks);
|
||||
|
||||
bool operator==(const KnownFontSpec &other) const;
|
||||
bool operator!=(const KnownFontSpec &other) const;
|
||||
|
||||
private:
|
||||
std::string m_path;
|
||||
int m_size;
|
||||
bool m_aa;
|
||||
PortabilityLayer::FontHacks m_hacks;
|
||||
};
|
||||
|
||||
|
||||
KnownFontSpec::KnownFontSpec()
|
||||
: m_size(0)
|
||||
, m_aa(false)
|
||||
, m_hacks(PortabilityLayer::FontHacks_None)
|
||||
{
|
||||
}
|
||||
|
||||
KnownFontSpec::KnownFontSpec(const char *path, int size, bool aa, PortabilityLayer::FontHacks hacks)
|
||||
: m_path(path)
|
||||
, m_size(size)
|
||||
, m_aa(aa)
|
||||
, m_hacks(hacks)
|
||||
{
|
||||
}
|
||||
|
||||
bool KnownFontSpec::operator==(const KnownFontSpec &other) const
|
||||
{
|
||||
return !((*this) != other);
|
||||
}
|
||||
|
||||
bool KnownFontSpec::operator!=(const KnownFontSpec &other) const
|
||||
{
|
||||
return m_path != other.m_path ||
|
||||
m_size != other.m_size ||
|
||||
m_aa != other.m_aa ||
|
||||
m_hacks != other.m_hacks;
|
||||
}
|
||||
|
||||
int toolMain(int argc, const char **argv)
|
||||
{
|
||||
GpFontHandlerProperties fhProperties;
|
||||
fhProperties.m_type = EGpFontHandlerType_FreeType2;
|
||||
|
||||
IGpFontHandler *ft2Handler = GpDriver_CreateFontHandler_FreeType2(fhProperties);
|
||||
|
||||
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
|
||||
PortabilityLayer::FontRenderer *fontRenderer = PortabilityLayer::FontRenderer::GetInstance();
|
||||
fontManager->Init();
|
||||
|
||||
std::vector<std::string> paths;
|
||||
std::vector<PortabilityLayer::RenderedFontCatalogRFontEntry> catalog;
|
||||
std::vector<KnownFontSpec> fontSpecs;
|
||||
|
||||
FILE *manifestF = fopen_utf8("Packaged/FontCacheManifest.json", "wb");
|
||||
|
||||
fprintf(manifestF, "{\n");
|
||||
fprintf(manifestF, "\t\"add\" :\n");
|
||||
fprintf(manifestF, "\t{\n");
|
||||
fprintf(manifestF, "\t\t\"RFCT/1000.bin\" : \"Packaged/FontCacheCatalog.bin\"");
|
||||
|
||||
int numFontsEmitted = 0;
|
||||
for (int presetIndex = 0; presetIndex < PortabilityLayer::FontPresets::kCount; presetIndex++)
|
||||
{
|
||||
int size = 0;
|
||||
int flags = 0;
|
||||
bool aa = false;
|
||||
PortabilityLayer::FontFamilyID_t fontFamilyID;
|
||||
|
||||
fontManager->GetFontPreset(static_cast<PortabilityLayer::FontPreset_t>(presetIndex), &fontFamilyID, &size, &flags, &aa);
|
||||
PortabilityLayer::FontFamily *fontFamily = fontManager->GetFont(fontFamilyID);
|
||||
|
||||
int variation = fontFamily->GetVariationForFlags(flags);
|
||||
|
||||
PortabilityLayer::FontHacks hacks;
|
||||
const char *path = nullptr;
|
||||
fontFamily->GetFontSpec(variation, hacks, path);
|
||||
|
||||
KnownFontSpec spec(path, size, aa, hacks);
|
||||
|
||||
if (std::find(fontSpecs.begin(), fontSpecs.end(), spec) != fontSpecs.end())
|
||||
continue;
|
||||
|
||||
fontSpecs.push_back(spec);
|
||||
|
||||
std::string resPath = std::string("Resources/") + path;
|
||||
FILE *fontFile = fopen_utf8(resPath.c_str(), "rb");
|
||||
|
||||
if (fontFile)
|
||||
{
|
||||
PortabilityLayer::CFileStream stream(fontFile);
|
||||
|
||||
IGpFont *font = ft2Handler->LoadFont(&stream);
|
||||
if (!ft2Handler->KeepStreamOpen())
|
||||
stream.Close();
|
||||
|
||||
PortabilityLayer::RenderedFont *rfont = fontRenderer->RenderFont(font, size, aa, hacks);
|
||||
|
||||
|
||||
{
|
||||
char fontPath[1024];
|
||||
sprintf(fontPath, "Packaged/CachedFont%i.bin", numFontsEmitted);
|
||||
|
||||
FILE *cachedFontF = fopen_utf8(fontPath, "wb");
|
||||
PortabilityLayer::CFileStream cacheStream(cachedFontF);
|
||||
|
||||
fontRenderer->SaveCache(rfont, &cacheStream);
|
||||
cacheStream.Close();
|
||||
|
||||
fprintf(manifestF, ",\n\t\t\"RFNT/%i.bin\" : \"%s\"", 1000 + numFontsEmitted, fontPath);
|
||||
}
|
||||
|
||||
rfont->Destroy();
|
||||
|
||||
font->Destroy();
|
||||
|
||||
PortabilityLayer::RenderedFontCatalogRFontEntry catEntry;
|
||||
catEntry.m_fontSize = static_cast<uint8_t>(size);
|
||||
catEntry.m_hacks = static_cast<uint8_t>(hacks);
|
||||
catEntry.m_isAA = aa ? 1 : 0;
|
||||
catEntry.m_pathIndex = 0;
|
||||
|
||||
bool foundPath = false;
|
||||
for (size_t i = 0; i < paths.size(); i++)
|
||||
{
|
||||
if (paths[i] == path)
|
||||
{
|
||||
catEntry.m_pathIndex = static_cast<uint8_t>(i);
|
||||
foundPath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundPath)
|
||||
{
|
||||
catEntry.m_pathIndex = static_cast<uint8_t>(paths.size());
|
||||
paths.push_back(std::string(path));
|
||||
}
|
||||
|
||||
catalog.push_back(catEntry);
|
||||
|
||||
numFontsEmitted++;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(manifestF, "\n\t},\n");
|
||||
fprintf(manifestF, "\t\"delete\" :\n");
|
||||
fprintf(manifestF, "\t[\n");
|
||||
fprintf(manifestF, "\t]\n");
|
||||
fprintf(manifestF, "}\n");
|
||||
|
||||
PortabilityLayer::RenderedFontCatalogHeader catHeader;
|
||||
|
||||
FILE *catF = fopen_utf8("Packaged/FontCacheCatalog.bin", "wb");
|
||||
|
||||
catHeader.m_version = PortabilityLayer::RenderedFontCatalogHeader::kVersion;
|
||||
catHeader.m_pathsOffset = static_cast<uint32_t>(sizeof(PortabilityLayer::RenderedFontCatalogHeader) + paths.size() * sizeof(PortabilityLayer::RenderedFontCatalogPathEntry) + numFontsEmitted * sizeof(PortabilityLayer::RenderedFontCatalogRFontEntry));
|
||||
catHeader.m_numPaths = static_cast<uint16_t>(paths.size());
|
||||
catHeader.m_numRFonts = static_cast<uint16_t>(numFontsEmitted);
|
||||
|
||||
fwrite(&catHeader, sizeof(catHeader), 1, catF);
|
||||
|
||||
PortabilityLayer::RenderedFontCatalogPathEntry pathEntry;
|
||||
pathEntry.m_pathOffset = 0;
|
||||
pathEntry.m_pathSize = 0;
|
||||
for (size_t i = 0; i < paths.size(); i++)
|
||||
{
|
||||
pathEntry.m_pathOffset = static_cast<uint16_t>(pathEntry.m_pathOffset) + pathEntry.m_pathSize;
|
||||
pathEntry.m_pathSize = static_cast<uint16_t>(paths[i].size());
|
||||
|
||||
fwrite(&pathEntry, sizeof(pathEntry), 1, catF);
|
||||
}
|
||||
|
||||
fwrite(&catalog[0], sizeof(PortabilityLayer::RenderedFontCatalogRFontEntry), catalog.size(), catF);
|
||||
|
||||
for (size_t i = 0; i < paths.size(); i++)
|
||||
{
|
||||
const std::string &str = paths[i];
|
||||
fwrite(&str[0], str.size(), 1, catF);
|
||||
}
|
||||
|
||||
fclose(catF);
|
||||
|
||||
return 0;
|
||||
}
|
101
GenerateFonts/GenerateFonts.vcxproj
Normal file
101
GenerateFonts/GenerateFonts.vcxproj
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{3B7FD18D-7A50-4DF5-AC25-543E539BFACE}</ProjectGuid>
|
||||
<RootNamespace>GenerateFonts</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Common.props" />
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\PortabilityLayer.props" />
|
||||
<Import Project="..\AerofoilWin.props" />
|
||||
<Import Project="..\Debug.props" />
|
||||
<Import Project="..\WindowsUnicodeToolShim.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\Common.props" />
|
||||
<Import Project="..\GpCommon.props" />
|
||||
<Import Project="..\PortabilityLayer.props" />
|
||||
<Import Project="..\AerofoilWin.props" />
|
||||
<Import Project="..\Release.props" />
|
||||
<Import Project="..\WindowsUnicodeToolShim.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GpFontHandler_FreeType2\GpFontHandler_FreeType2.vcxproj">
|
||||
<Project>{4b564030-8985-4975-91e1-e1b2c16ae2a1}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
|
||||
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
|
||||
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GenerateFonts.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
GenerateFonts/GenerateFonts.vcxproj.filters
Normal file
22
GenerateFonts/GenerateFonts.vcxproj.filters
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GenerateFonts.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Reference in New Issue
Block a user