Font system refactor, use pre-rendered fonts

This commit is contained in:
elasota
2021-03-27 02:08:03 -04:00
parent c87f238563
commit 50f420d2b1
63 changed files with 976 additions and 1294 deletions

View File

@@ -1,8 +1,5 @@
#pragma once
#ifndef __PL_CFILESTREAM_H__
#define __PL_CFILESTREAM_H__
#include <stdio.h>
#include "CoreDefs.h"
@@ -38,5 +35,3 @@ namespace PortabilityLayer
bool m_seekable;
};
}
#endif

View File

@@ -199,7 +199,7 @@ namespace PortabilityLayer
void FileBrowserUIImpl::DrawHeaders()
{
PortabilityLayer::RenderedFont *font = GetApplicationFont(12, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *font = GetFont(FontPresets::kApplication12Bold);
ResolveCachingColor blackColor = StdColors::Black();
@@ -212,7 +212,7 @@ namespace PortabilityLayer
if (!m_entries.MMBlock())
return;
PortabilityLayer::RenderedFont *font = GetApplicationFont(12, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *font = GetFont(FontPresets::kApplication12Bold);
GpRenderedFontMetrics metrics = font->GetMetrics();
int32_t spacing = metrics.m_linegap;
@@ -634,8 +634,8 @@ namespace PortabilityLayer
PortabilityLayer::WindowDef wdef = PortabilityLayer::WindowDef::Create(windowRect, PortabilityLayer::WindowStyleFlags::kAlert, true, 0, 0, PSTR(""));
PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black();
PortabilityLayer::RenderedFont *font = GetApplicationFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *fontLight = GetApplicationFont(8, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *font = GetFont(FontPresets::kApplication12Bold);
PortabilityLayer::RenderedFont *fontLight = GetFont(FontPresets::kApplication8);
int16_t verticalPoint = 16 + font->GetMetrics().m_ascent;
int16_t horizontalOffset = 16;

View File

@@ -38,10 +38,10 @@ namespace PortabilityLayer
m_defaultVariation = defaultVariation;
}
int FontFamily::GetVariationForFlags(int variation) const
int FontFamily::GetVariationForFlags(int flags) const
{
if (m_fontSpecs[variation].m_isRegistered)
return variation;
if (m_fontSpecs[flags].m_isRegistered)
return flags;
if (m_fontSpecs[0].m_isRegistered)
return 0;
@@ -111,9 +111,20 @@ namespace PortabilityLayer
return m_fontSpecs[variation].m_hacks;
}
int FontFamily::GetCacheID() const
bool FontFamily::GetFontSpec(int variation, FontHacks &outHacks, const char *&outPath)
{
return m_cacheID;
if (!m_fontSpecs[variation].m_isRegistered)
return false;
outHacks = m_fontSpecs[variation].m_hacks;
outPath = m_fontSpecs[variation].m_fontPath;
return true;
}
FontFamilyID_t FontFamily::GetFamilyID() const
{
return m_familyID;
}
void FontFamily::PurgeCache()
@@ -128,13 +139,13 @@ namespace PortabilityLayer
}
}
FontFamily *FontFamily::Create(int cacheID)
FontFamily *FontFamily::Create(FontFamilyID_t familyID)
{
void *storage = malloc(sizeof(FontFamily));
if (!storage)
return nullptr;
return new (storage) FontFamily(cacheID);
return new (storage) FontFamily(familyID);
}
void FontFamily::Destroy()
@@ -143,9 +154,9 @@ namespace PortabilityLayer
free(this);
}
FontFamily::FontFamily(int cacheID)
FontFamily::FontFamily(FontFamilyID_t familyID)
: m_defaultVariation(0)
, m_cacheID(cacheID)
, m_familyID(familyID)
{
}

View File

@@ -1,6 +1,8 @@
#pragma once
#include "FontFamilyID.h"
#include "FontHacks.h"
#include <stdint.h>
class PLPasStr;
@@ -24,16 +26,17 @@ namespace PortabilityLayer
void AddFont(int flags, const char *path, FontHacks fontHacks);
void SetDefaultVariation(int defaultVariation);
bool GetFontSpec(int variation, FontHacks &outHacks, const char *&outPath);
int GetVariationForFlags(int variation) const;
int GetVariationForFlags(int flags) const;
IGpFont *GetFontForVariation(int variation);
FontHacks GetHacksForVariation(int variation) const;
int GetCacheID() const;
FontFamilyID_t GetFamilyID() const;
void PurgeCache();
static FontFamily *Create(int cacheID);
static FontFamily *Create(FontFamilyID_t familyID);
void Destroy();
private:
@@ -49,9 +52,9 @@ namespace PortabilityLayer
FontSpec m_fontSpecs[kNumVariations];
uint8_t m_defaultVariation;
int m_cacheID;
FontFamilyID_t m_familyID;
explicit FontFamily(int cacheID);
explicit FontFamily(FontFamilyID_t familyID);
~FontFamily();
};
}

View File

@@ -0,0 +1,19 @@
#pragma once
namespace PortabilityLayer
{
namespace FontFamilyIDs
{
enum FontFamilyID
{
kSystem,
kApplication,
kMonospace,
kHandwriting,
kCount
};
}
typedef FontFamilyIDs::FontFamilyID FontFamilyID_t;
}

View File

@@ -2,13 +2,18 @@
#include "FontFamily.h"
#include "FontRenderer.h"
#include "FileManager.h"
#include "GpIOStream.h"
#include "IGpFileSystem.h"
#include "IGpFont.h"
#include "RenderedFont.h"
#include "MemReaderStream.h"
#include "PLBigEndian.h"
#include "PLDrivers.h"
#include "RenderedFontCatalog.h"
#include "RenderedFont.h"
#include "ResTypeID.h"
#include "ResourceManager.h"
#include <stdio.h>
#include <string.h>
@@ -24,15 +29,12 @@ namespace PortabilityLayer
void Init() override;
void Shutdown() override;
FontFamily *GetSystemFont(int textSize, int variationFlags) const override;
FontFamily *GetApplicationFont(int textSize, int variationFlags) const override;
FontFamily *GetHandwritingFont(int textSize, int variationFlags) const override;
FontFamily *GetMonospaceFont(int textSize, int variationFlags) const override;
FontFamily *GetFont(FontFamilyID_t fontFamilyID) const override;
void GetFontPreset(FontPreset_t fontPreset, FontFamilyID_t *outFamilyID, int *outSize, int *outVariationFlags, bool *outAA) const override;
RenderedFont *GetRenderedFontFromFamily(FontFamily *font, int size, bool aa, int flags) override;
RenderedFont *LoadCachedRenderedFont(int cacheID, int size, bool aa, int flags) const override;
void SaveCachedRenderedFont(const RenderedFont *rfont, int cacheID, int size, bool aa, int flags) const override;
RenderedFont *LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags) override;
void PurgeCache() override;
@@ -40,12 +42,6 @@ namespace PortabilityLayer
private:
static const unsigned int kNumCachedRenderedFonts = 32;
static const int kSystemFontCacheID = 1;
static const int kApplicationFontCacheID = 2;
static const int kHandwritingFontCacheID = 3;
static const int kMonospaceFontCacheID = 4;
static const int kFontCacheVersion = 2;
static const int kFontCacheNameSize = 64;
struct CachedRenderedFont
{
@@ -56,6 +52,14 @@ namespace PortabilityLayer
bool m_aa;
};
struct FontPreset
{
FontFamilyID_t m_familyID;
int m_textSize;
int m_variationFlags;
bool m_aa;
};
FontManagerImpl();
bool FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF);
@@ -64,57 +68,49 @@ namespace PortabilityLayer
void ResetUsageCounter();
static int CRFSortPredicate(const void *a, const void *b);
static void GenerateCacheFileName(char(&str)[kFontCacheNameSize], int cacheID, int size, bool aa, int flags);
FontFamily *m_systemFont;
FontFamily *m_applicationFont;
FontFamily *m_handwritingFont;
FontFamily *m_monospaceFont;
FontFamily *m_fontFamilies[FontFamilyIDs::kCount];
uint32_t m_usageCounter;
CachedRenderedFont m_cachedRenderedFonts[kNumCachedRenderedFonts];
IResourceArchive *m_fontArchive;
PortabilityLayer::CompositeFile *m_fontArchiveFile;
THandle<void> m_fontArchiveCatalogData;
static FontManagerImpl ms_instance;
static FontPreset ms_fontPresets[FontPresets::kCount];
};
void FontManagerImpl::Init()
{
m_systemFont = FontFamily::Create(kSystemFontCacheID);
m_applicationFont = FontFamily::Create(kApplicationFontCacheID);
m_handwritingFont = FontFamily::Create(kHandwritingFontCacheID);
m_monospaceFont = FontFamily::Create(kMonospaceFontCacheID);
for (int i = 0; i < FontFamilyIDs::kCount; i++)
m_fontFamilies[static_cast<FontFamilyID_t>(i)] = FontFamily::Create(static_cast<FontFamilyID_t>(i));
if (m_systemFont)
m_systemFont->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-ExtraBold.ttf", FontHacks_None);
if (m_fontFamilies[FontFamilyIDs::kSystem])
m_fontFamilies[FontFamilyIDs::kSystem]->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-ExtraBold.ttf", FontHacks_None);
if (m_applicationFont)
if (m_fontFamilies[FontFamilyIDs::kApplication])
{
m_applicationFont->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-SemiBold.ttf", FontHacks_None);
m_applicationFont->AddFont(FontFamilyFlag_Bold, "Fonts/OpenSans/OpenSans-Bold.ttf", FontHacks_None);
m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_None, "Fonts/OpenSans/OpenSans-SemiBold.ttf", FontHacks_None);
m_fontFamilies[FontFamilyIDs::kApplication]->AddFont(FontFamilyFlag_Bold, "Fonts/OpenSans/OpenSans-Bold.ttf", FontHacks_None);
}
if (m_handwritingFont)
m_handwritingFont->AddFont(FontFamilyFlag_None, "Fonts/GochiHand/GochiHand-Regular.ttf", FontHacks_None);
if (m_fontFamilies[FontFamilyIDs::kHandwriting])
m_fontFamilies[FontFamilyIDs::kHandwriting]->AddFont(FontFamilyFlag_None, "Fonts/GochiHand/GochiHand-Regular.ttf", FontHacks_None);
if (m_monospaceFont)
m_monospaceFont->AddFont(FontFamilyFlag_None, "Fonts/Roboto/RobotoMono-Regular.ttf", FontHacks_None);
if (m_fontFamilies[FontFamilyIDs::kMonospace])
m_fontFamilies[FontFamilyIDs::kMonospace]->AddFont(FontFamilyFlag_None, "Fonts/Roboto/RobotoMono-Regular.ttf", FontHacks_None);
memset(m_cachedRenderedFonts, 0, sizeof(m_cachedRenderedFonts));
}
void FontManagerImpl::Shutdown()
{
if (m_systemFont)
m_systemFont->Destroy();
if (m_applicationFont)
m_applicationFont->Destroy();
if (m_handwritingFont)
m_handwritingFont->Destroy();
if (m_monospaceFont)
m_monospaceFont->Destroy();
for (int fid = 0; fid < FontFamilyIDs::kCount; fid++)
{
if (m_fontFamilies[fid])
m_fontFamilies[fid]->Destroy();
}
IGpFontHandler *hfh = PLDrivers::GetFontHandler();
@@ -126,27 +122,37 @@ namespace PortabilityLayer
}
}
FontFamily *FontManagerImpl::GetSystemFont(int textSize, int variationFlags) const
FontFamily *FontManagerImpl::GetFont(FontFamilyID_t fontFamilyID) const
{
return m_systemFont;
return m_fontFamilies[fontFamilyID];
}
FontFamily *FontManagerImpl::GetApplicationFont(int textSize, int variationFlags) const
void FontManagerImpl::GetFontPreset(FontPreset_t preset, FontFamilyID_t *outFamilyID, int *outSize, int *outVariationFlags, bool *outAA) const
{
if (textSize < 11 && (variationFlags & FontFamilyFlag_Bold) != 0)
return m_systemFont; // Use heavier font below 11pt
if (outSize)
*outSize = ms_fontPresets[preset].m_textSize;
return m_applicationFont;
}
if (outVariationFlags)
*outVariationFlags = ms_fontPresets[preset].m_variationFlags;
FontFamily *FontManagerImpl::GetHandwritingFont(int textSize, int variationFlags) const
{
return m_handwritingFont;
}
if (outAA)
*outAA = ms_fontPresets[preset].m_aa;
FontFamily *FontManagerImpl::GetMonospaceFont(int textSize, int variationFlags) const
{
return m_monospaceFont;
if (outFamilyID)
{
switch (ms_fontPresets[preset].m_familyID)
{
case FontFamilyIDs::kApplication:
if (ms_fontPresets[preset].m_textSize < 11 && (ms_fontPresets[preset].m_variationFlags & FontFamilyFlag_Bold) != 0)
*outFamilyID = FontFamilyIDs::kSystem; // Use heavier font below 11pt
else
*outFamilyID = FontFamilyIDs::kApplication;
break;
default:
*outFamilyID = ms_fontPresets[preset].m_familyID;
break;
}
}
}
bool FontManagerImpl::FindOrReserveCacheSlot(int cacheID, int size, bool aa, CachedRenderedFont *&outCacheSlot, RenderedFont *&outRF)
@@ -206,15 +212,15 @@ namespace PortabilityLayer
RenderedFont *rfont = nullptr;
CachedRenderedFont *cacheSlot = nullptr;
int cacheID = fontFamily->GetCacheID();
FontFamilyID_t familyID = fontFamily->GetFamilyID();
if (this->FindOrReserveCacheSlot(cacheID, size, aa, cacheSlot, rfont))
if (this->FindOrReserveCacheSlot(familyID, size, aa, cacheSlot, rfont))
return rfont;
rfont = fm->LoadCachedRenderedFont(cacheID, size, aa, flags);
rfont = fm->LoadCachedRenderedFont(familyID, size, aa, flags);
if (rfont)
{
ReplaceCachedRenderedFont(*cacheSlot, rfont, cacheID, size, aa, flags);
ReplaceCachedRenderedFont(*cacheSlot, rfont, familyID, size, aa, flags);
return rfont;
}
@@ -228,9 +234,7 @@ namespace PortabilityLayer
rfont = FontRenderer::GetInstance()->RenderFont(hostFont, size, aa, fontFamily->GetHacksForVariation(variation));
if (rfont)
{
fm->SaveCachedRenderedFont(rfont, fontFamily->GetCacheID(), size, aa, flags);
ReplaceCachedRenderedFont(*cacheSlot, rfont, cacheID, size, aa, flags);
ReplaceCachedRenderedFont(*cacheSlot, rfont, familyID, size, aa, flags);
return rfont;
}
@@ -238,60 +242,110 @@ namespace PortabilityLayer
return rfont;
}
RenderedFont *FontManagerImpl::LoadCachedRenderedFont(int cacheID, int size, bool aa, int flags) const
RenderedFont *FontManagerImpl::LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags)
{
char filename[kFontCacheNameSize];
GenerateCacheFileName(filename, cacheID, size, aa, flags);
GpIOStream *stream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFontCache, filename, false, GpFileCreationDispositions::kOpenExisting);
if (!stream)
return nullptr;
BEUInt32_t version;
if (stream->Read(&version, sizeof(version)) != sizeof(version) || version != kFontCacheVersion)
if (!m_fontArchive)
{
stream->Close();
return nullptr;
m_fontArchiveFile = PortabilityLayer::FileManager::GetInstance()->OpenCompositeFile(VirtualDirectories::kApplicationData, PSTR("Fonts"));
if (!m_fontArchiveFile)
return nullptr;
m_fontArchive = PortabilityLayer::ResourceManager::GetInstance()->LoadResFile(m_fontArchiveFile);
if (!m_fontArchive)
{
m_fontArchiveFile->Close();
return nullptr;
}
m_fontArchiveCatalogData = m_fontArchive->LoadResource('RFCT', 1000);
if (!m_fontArchiveCatalogData)
{
m_fontArchive->Destroy();
m_fontArchiveFile->Close();
return nullptr;
}
}
RenderedFont *rfont = PortabilityLayer::FontRenderer::GetInstance()->LoadCache(stream);
stream->Close();
FontFamily *fontFamily = this->GetFont(familyID);
int variation = fontFamily->GetVariationForFlags(flags);
FontHacks hacks = FontHacks_None;
const char *path = nullptr;
if (!fontFamily->GetFontSpec(variation, hacks, path))
return nullptr;
size_t pathLen = strlen(path);
// Parse font cache header
const uint8_t *catalogBytes = static_cast<const uint8_t*>(*m_fontArchiveCatalogData);
RenderedFontCatalogHeader catHeader;
memcpy(&catHeader, catalogBytes, sizeof(catHeader));
if (catHeader.m_version != RenderedFontCatalogHeader::kVersion)
return nullptr;
size_t numPaths = catHeader.m_numPaths;
size_t numFonts = catHeader.m_numRFonts;
const uint8_t *pathsBytes = catalogBytes + catHeader.m_pathsOffset;
const uint8_t *pathEntryBytes = catalogBytes + sizeof(RenderedFontCatalogHeader);
const uint8_t *fontEntryBytes = pathEntryBytes + sizeof(RenderedFontCatalogPathEntry) * numPaths;
size_t pathIndex = numPaths;
for (size_t i = 0; i < numPaths; i++)
{
RenderedFontCatalogPathEntry pathEntry;
memcpy(&pathEntry, pathEntryBytes + i * sizeof(RenderedFontCatalogPathEntry), sizeof(RenderedFontCatalogPathEntry));
if (pathEntry.m_pathSize != pathLen)
continue;
if (!memcmp(pathsBytes + pathEntry.m_pathOffset, path, pathLen))
{
pathIndex = i;
break;
}
}
if (pathIndex == numPaths)
return nullptr;
size_t fontIndex = numFonts;
for (size_t i = 0; i < numFonts; i++)
{
RenderedFontCatalogRFontEntry fontEntry;
memcpy(&fontEntry, fontEntryBytes + i * sizeof(RenderedFontCatalogRFontEntry), sizeof(RenderedFontCatalogRFontEntry));
if (fontEntry.m_pathIndex == pathIndex && static_cast<FontHacks>(fontEntry.m_hacks) == hacks && fontEntry.m_fontSize == size && (fontEntry.m_isAA != 0) == aa)
{
fontIndex = i;
break;
}
}
if (fontIndex == numFonts)
return nullptr;
THandle<void> res = m_fontArchive->LoadResource('RFNT', 1000 + static_cast<int>(fontIndex));
if (!res)
return nullptr;
PortabilityLayer::MemReaderStream stream(*res, res.MMBlock()->m_size);
RenderedFont *rfont = PortabilityLayer::FontRenderer::GetInstance()->LoadCache(&stream);
res.Dispose();
return rfont;
}
void FontManagerImpl::SaveCachedRenderedFont(const RenderedFont *rfont, int cacheID, int size, bool aa, int flags) const
{
char filename[kFontCacheNameSize];
GenerateCacheFileName(filename, cacheID, size, aa, flags);
GpIOStream *stream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFontCache, filename, true, GpFileCreationDispositions::kCreateOrOverwrite);
if (!stream)
return;
BEUInt32_t zero32(0);
if (stream->Write(&zero32, sizeof(zero32)) != sizeof(zero32))
{
stream->Close();
return;
}
if (PortabilityLayer::FontRenderer::GetInstance()->SaveCache(rfont, stream))
{
BEUInt32_t version(kFontCacheVersion);
stream->SeekStart(0);
stream->Write(&version, sizeof(version));
}
stream->Close();
}
void FontManagerImpl::PurgeCache()
{
m_systemFont->PurgeCache();
m_applicationFont->PurgeCache();
m_handwritingFont->PurgeCache();
m_monospaceFont->PurgeCache();
for (int fid = 0; fid < FontFamilyIDs::kCount; fid++)
{
if (m_fontFamilies[fid])
m_fontFamilies[fid]->PurgeCache();
}
}
FontManagerImpl *FontManagerImpl::GetInstance()
@@ -300,8 +354,11 @@ namespace PortabilityLayer
}
FontManagerImpl::FontManagerImpl()
: m_systemFont(nullptr)
: m_fontArchive(nullptr)
, m_fontArchiveFile(nullptr)
{
for (int fid = 0; fid < FontFamilyIDs::kCount; fid++)
m_fontFamilies[fid] = nullptr;
}
void FontManagerImpl::ResetUsageCounter()
@@ -345,10 +402,26 @@ namespace PortabilityLayer
return 0;
}
void FontManagerImpl::GenerateCacheFileName(char(&str)[kFontCacheNameSize], int cacheID, int size, bool aa, int flags)
FontManagerImpl::FontPreset FontManagerImpl::ms_fontPresets[FontPresets::kCount] =
{
sprintf(str, "rf_%i_%i_%s_%i.cache", cacheID, size, aa ? "aa" : "mc", flags);
}
{ FontFamilyIDs::kSystem, 12, FontFamilyFlag_None, true },
{ FontFamilyIDs::kSystem, 12, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 8, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 9, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 9, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 10, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 12, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 14, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 14, FontFamilyFlag_Bold, true },
{ FontFamilyIDs::kApplication, 18, FontFamilyFlag_None, true },
{ FontFamilyIDs::kApplication, 40, FontFamilyFlag_None, true },
{ FontFamilyIDs::kMonospace, 10, FontFamilyFlag_None, true },
{ FontFamilyIDs::kHandwriting, 24, FontFamilyFlag_None, true },
{ FontFamilyIDs::kHandwriting, 48, FontFamilyFlag_None, true },
};
FontManagerImpl FontManagerImpl::ms_instance;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "FontHacks.h"
#include "FontFamilyID.h"
struct IGpFont;
@@ -9,21 +10,46 @@ namespace PortabilityLayer
class FontFamily;
class RenderedFont;
namespace FontPresets
{
enum FontPreset
{
kSystem12,
kSystem12Bold,
kApplication8,
kApplication9,
kApplication9Bold,
kApplication10Bold,
kApplication12Bold,
kApplication14,
kApplication14Bold,
kApplication18,
kApplication40,
kMono10,
kHandwriting24,
kHandwriting48,
kCount,
};
}
typedef FontPresets::FontPreset FontPreset_t;
class FontManager
{
public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual FontFamily *GetSystemFont(int fontSize, int variationFlags) const = 0;
virtual FontFamily *GetApplicationFont(int fontSize, int variationFlags) const = 0;
virtual FontFamily *GetHandwritingFont(int fontSize, int variationFlags) const = 0;
virtual FontFamily *GetMonospaceFont(int fontSize, int variationFlags) const = 0;
virtual FontFamily *GetFont(FontFamilyID_t fontFamilyID) const = 0;
virtual void GetFontPreset(FontPreset_t fontPreset, FontFamilyID_t *outFamilyID, int *outSize, int *outVariationFlags, bool *outAA) const = 0;
virtual RenderedFont *GetRenderedFontFromFamily(FontFamily *fontFamily, int fontSize, bool aa, int flags) = 0;
virtual RenderedFont *LoadCachedRenderedFont(int cacheID, int size, bool aa, int flags) const = 0;
virtual void SaveCachedRenderedFont(const RenderedFont *rfont, int cacheID, int size, bool aa, int flags) const = 0;
virtual RenderedFont *LoadCachedRenderedFont(FontFamilyID_t familyID, int size, bool aa, int flags) = 0;
virtual void PurgeCache() = 0;

View File

@@ -44,19 +44,42 @@ namespace PortabilityLayer
struct CacheHeader
{
BEUInt32_t m_cacheVersion;
BEUInt32_t m_glyphDataUncompressedSize;
BEUInt32_t m_glyphDataCompressedSize;
BEUInt32_t m_sizeSize;
BEUInt32_t m_glyphDataSize;
BEUInt32_t m_isAA;
};
static const uint32_t kRFontCacheVersion = 2;
struct SerializedGlyphMetrics
{
BEUInt32_t m_glyphDataPitch;
BEUInt32_t m_glyphWidth;
BEUInt32_t m_glyphHeight;
BEInt16_t m_bearingX;
BEInt16_t m_bearingY;
BEInt16_t m_advanceX;
};
struct SerializedFontMetrics
{
BEInt32_t m_ascent;
BEInt32_t m_descent;
BEInt32_t m_linegap;
};
static const uint32_t kRFontCacheVersion = 3;
RenderedFontImpl(void *data, size_t dataSize, bool aa);
~RenderedFontImpl();
bool LoadInternal(GpIOStream *stream, size_t compressedDataSize);
bool LoadInternal(GpIOStream *stream, size_t dataSize);
static SerializedGlyphMetrics SerializeGlyphMetrics(const GpRenderedGlyphMetrics &metrics);
static GpRenderedGlyphMetrics DeserializeGlyphMetrics(const SerializedGlyphMetrics &metrics);
static SerializedFontMetrics SerializeFontMetrics(const GpRenderedFontMetrics &metrics);
static GpRenderedFontMetrics DeserializeFontMetrics(const SerializedFontMetrics &metrics);
size_t m_dataOffsets[256];
GpRenderedGlyphMetrics m_glyphMetrics[256];
@@ -143,14 +166,11 @@ namespace PortabilityLayer
if (header.m_cacheVersion != kRFontCacheVersion)
return nullptr;
if (header.m_sizeSize != sizeof(size_t))
return nullptr;
RenderedFontImpl *rfont = RenderedFontImpl::Create(header.m_glyphDataUncompressedSize, header.m_isAA != 0);
RenderedFontImpl *rfont = RenderedFontImpl::Create(header.m_glyphDataSize, header.m_isAA != 0);
if (!rfont)
return nullptr;
if (!rfont->LoadInternal(stream, header.m_glyphDataCompressedSize))
if (!rfont->LoadInternal(stream, header.m_glyphDataSize))
{
rfont->Destroy();
return nullptr;
@@ -163,51 +183,35 @@ namespace PortabilityLayer
{
CacheHeader header;
header.m_cacheVersion = kRFontCacheVersion;
header.m_glyphDataUncompressedSize = static_cast<uint32_t>(this->m_dataSize);
header.m_glyphDataCompressedSize = 0;
header.m_isAA = m_isAntiAliased;
header.m_sizeSize = sizeof(size_t);
header.m_glyphDataSize = static_cast<uint32_t>(this->m_dataSize);
header.m_isAA = m_isAntiAliased ? 1 : 0;
GpUFilePos_t headerPos = stream->Tell();
if (stream->Write(&header, sizeof(header)) != sizeof(header))
return false;
DeflateContext *deflateContext = DeflateContext::Create(stream, 9);
if (!deflateContext)
if (!stream->WriteExact(m_data, m_dataSize))
return false;
GpUFilePos_t dataStartPos = stream->Tell();
if (!deflateContext->Append(m_data, m_dataSize) || !deflateContext->Flush())
for (size_t i = 0; i < sizeof(m_dataOffsets) / sizeof(m_dataOffsets[0]); i++)
{
deflateContext->Destroy();
return false;
BEUInt32_t dataOffset = BEUInt32_t(static_cast<uint32_t>(m_dataOffsets[i]));
if (!stream->WriteExact(&dataOffset, sizeof(dataOffset)))
return false;
}
deflateContext->Destroy();
for (size_t i = 0; i < sizeof(m_glyphMetrics) / sizeof(m_glyphMetrics[0]); i++)
{
SerializedGlyphMetrics serialized = SerializeGlyphMetrics(m_glyphMetrics[i]);
GpUFilePos_t dataEndPos = stream->Tell();
if (!stream->WriteExact(&serialized, sizeof(serialized)))
return false;
}
if (stream->Write(m_dataOffsets, sizeof(m_dataOffsets)) != sizeof(m_dataOffsets))
return false;
SerializedFontMetrics fontMetrics = SerializeFontMetrics(m_fontMetrics);
if (stream->Write(m_glyphMetrics, sizeof(m_glyphMetrics)) != sizeof(m_glyphMetrics))
return false;
if (stream->Write(&m_fontMetrics, sizeof(m_fontMetrics)) != sizeof(m_fontMetrics))
return false;
GpUFilePos_t endPos = stream->Tell();
if (!stream->SeekStart(headerPos))
return false;
header.m_glyphDataCompressedSize = dataEndPos - dataStartPos;
if (stream->Write(&header, sizeof(header)) != sizeof(header))
return false;
if (!stream->SeekStart(headerPos))
if (!stream->WriteExact(&fontMetrics, sizeof(fontMetrics)))
return false;
return true;
@@ -246,25 +250,86 @@ namespace PortabilityLayer
{
}
bool RenderedFontImpl::LoadInternal(GpIOStream *stream, size_t compressedDataSize)
bool RenderedFontImpl::LoadInternal(GpIOStream *stream, size_t dataSize)
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
if (!DeflateCodec::DecompressStream(stream, compressedDataSize, m_data, m_dataSize))
if (!stream->ReadExact(m_data, m_dataSize))
return false;
if (stream->Read(m_dataOffsets, sizeof(m_dataOffsets)) != sizeof(m_dataOffsets))
for (size_t i = 0; i < sizeof(m_dataOffsets) / sizeof(m_dataOffsets[0]); i++)
{
BEUInt32_t dataOffset;
if (!stream->ReadExact(&dataOffset, sizeof(dataOffset)))
return false;
m_dataOffsets[i] = dataOffset;
}
for (size_t i = 0; i < sizeof(m_glyphMetrics) / sizeof(m_glyphMetrics[0]); i++)
{
SerializedGlyphMetrics glyphMetrics;
if (!stream->ReadExact(&glyphMetrics, sizeof(glyphMetrics)))
return false;
m_glyphMetrics[i] = DeserializeGlyphMetrics(glyphMetrics);
}
SerializedFontMetrics fontMetrics;
if (!stream->ReadExact(&fontMetrics, sizeof(fontMetrics)))
return false;
if (stream->Read(m_glyphMetrics, sizeof(m_glyphMetrics)) != sizeof(m_glyphMetrics))
return false;
if (stream->Read(&m_fontMetrics, sizeof(m_fontMetrics)) != sizeof(m_fontMetrics))
return false;
m_fontMetrics = DeserializeFontMetrics(fontMetrics);
return true;
}
RenderedFontImpl::SerializedGlyphMetrics RenderedFontImpl::SerializeGlyphMetrics(const GpRenderedGlyphMetrics &metrics)
{
SerializedGlyphMetrics result;
result.m_advanceX = metrics.m_advanceX;
result.m_bearingX = metrics.m_bearingX;
result.m_bearingY = metrics.m_bearingY;
result.m_glyphDataPitch = static_cast<uint32_t>(metrics.m_glyphDataPitch);
result.m_glyphHeight = metrics.m_glyphHeight;
result.m_glyphWidth = metrics.m_glyphWidth;
return result;
}
GpRenderedGlyphMetrics RenderedFontImpl::DeserializeGlyphMetrics(const SerializedGlyphMetrics &metrics)
{
GpRenderedGlyphMetrics result;
result.m_advanceX = metrics.m_advanceX;
result.m_bearingX = metrics.m_bearingX;
result.m_bearingY = metrics.m_bearingY;
result.m_glyphDataPitch = static_cast<uint32_t>(metrics.m_glyphDataPitch);
result.m_glyphHeight = metrics.m_glyphHeight;
result.m_glyphWidth = metrics.m_glyphWidth;
return result;
}
RenderedFontImpl::SerializedFontMetrics RenderedFontImpl::SerializeFontMetrics(const GpRenderedFontMetrics &metrics)
{
SerializedFontMetrics result;
result.m_ascent = metrics.m_ascent;
result.m_descent = metrics.m_descent;
result.m_linegap = metrics.m_linegap;
return result;
}
GpRenderedFontMetrics RenderedFontImpl::DeserializeFontMetrics(const SerializedFontMetrics &metrics)
{
GpRenderedFontMetrics result;
result.m_ascent = metrics.m_ascent;
result.m_descent = metrics.m_descent;
result.m_linegap = metrics.m_linegap;
return result;
}
RenderedFont *FontRendererImpl::RenderFont(IGpFont *font, int size, bool aa, FontHacks fontHacks)
{

View File

@@ -209,8 +209,6 @@ namespace PortabilityLayer
static bool ItemIsSeparator(const Menu &menu, const MenuItem &item);
static const unsigned int kIconResID = 128;
static const unsigned int kMenuFontSize = 12;
static const unsigned int kTouchScreenMenuFontSize = 40;
static const unsigned int kMenuBarIconYOffset = 2;
static const unsigned int kMenuBarTextYOffset = 14;
static const unsigned int kTouchScreenMenuBarTextYOffset = 40;
@@ -235,6 +233,9 @@ namespace PortabilityLayer
static const int kMenuFontFlags = PortabilityLayer::FontFamilyFlag_Bold;
static const int kTouchScreenMenuFontFlags = PortabilityLayer::FontFamilyFlag_None;
static const FontPreset_t kMenuFontPreset = FontPresets::kSystem12Bold;
static const FontPreset_t kTouchScreenMenuFontPreset = FontPresets::kApplication40;
DrawSurface *m_menuBarGraf;
THandle<Menu> m_firstMenu;
@@ -954,12 +955,12 @@ namespace PortabilityLayer
unsigned int textYOffset = 0;
if (m_isTouchScreen)
{
sysFont = GetApplicationFont(kTouchScreenMenuFontSize, kTouchScreenMenuFontFlags, true);
sysFont = GetFont(kTouchScreenMenuFontPreset);
textYOffset = kTouchScreenMenuBarTextYOffset;
}
else
{
sysFont = GetSystemFont(kMenuFontSize, kMenuFontFlags, true);
sysFont = GetFont(kMenuFontPreset);
textYOffset = kMenuBarTextYOffset;
}
@@ -1086,29 +1087,17 @@ namespace PortabilityLayer
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::RenderedFont *rfont = nullptr;
PortabilityLayer::FontFamily *fontFamily = nullptr;
unsigned int fontSize = 0;
unsigned int fontFlags = 0;
if (m_isTouchScreen)
{
fontSize = kTouchScreenMenuFontSize;
fontFlags = PortabilityLayer::FontFamilyFlag_None;
fontFamily = PortabilityLayer::FontManager::GetInstance()->GetApplicationFont(kTouchScreenMenuFontSize, PortabilityLayer::FontFamilyFlag_None);
}
rfont = GetFont(kTouchScreenMenuFontPreset);
else
{
fontSize = kMenuFontSize;
fontFlags = kMenuFontFlags;
fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
}
rfont = GetFont(kMenuFontPreset);
if (!fontFamily)
return;
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, fontSize, true, fontFlags);
if (!rfont)
return;
@@ -1148,11 +1137,7 @@ namespace PortabilityLayer
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
if (!fontFamily)
return;
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, true, kMenuFontFlags);
PortabilityLayer::RenderedFont *rfont = GetFont(kMenuFontPreset);
if (!rfont)
return;
@@ -1498,7 +1483,7 @@ namespace PortabilityLayer
surface->FillRect(Rect::Create(static_cast<int16_t>(menu->layoutFinalHeight - 1), 1, static_cast<int16_t>(menu->layoutFinalHeight), static_cast<int16_t>(menu->layoutWidth - 1)), darkGrayColor);
}
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(kMenuFontSize, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(kMenuFontPreset);
const uint8_t *strBlob = static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents);

View File

@@ -445,7 +445,7 @@ namespace PortabilityLayer
ResolveCachingColor textCacheColor = textColor;
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
int32_t x = (m_rect.left + m_rect.right - static_cast<int32_t>(sysFont->MeasureString(reinterpret_cast<const uint8_t*>(m_text.UnsafeCharPtr()), m_text.Length()))) / 2;
int32_t y = (m_rect.top + m_rect.bottom + static_cast<int32_t>(sysFont->GetMetrics().m_ascent)) / 2;
@@ -535,7 +535,7 @@ namespace PortabilityLayer
}
}
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
int32_t textV = (m_rect.top + m_rect.bottom + sysFont->GetMetrics().m_ascent) / 2;
surface->DrawString(Point::Create(m_rect.left + checkFrameSize + 2, textV), m_text.ToShortStr(), *textColor, sysFont);
}
@@ -596,7 +596,7 @@ namespace PortabilityLayer
}
}
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
int32_t textV = (m_rect.top + m_rect.bottom + sysFont->GetMetrics().m_ascent) / 2;
surface->DrawString(Point::Create(m_rect.left + checkFrameSize + 2, textV), m_text.ToShortStr(), *textColor, sysFont);
}

View File

@@ -87,7 +87,7 @@ namespace PortabilityLayer
surface->FillRect(outerRect, blackColor);
surface->FillRect(innerRect, whiteColor);
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, PortabilityLayer::FontFamilyFlag_None, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12);
int32_t ascender = sysFont->GetMetrics().m_ascent;
int32_t lineGap = sysFont->GetMetrics().m_linegap;
@@ -1327,7 +1327,9 @@ namespace PortabilityLayer
FontFamily *EditboxWidget::GetFontFamily() const
{
return PortabilityLayer::FontManager::GetInstance()->GetSystemFont(12, FontFamilyFlag_None);
FontFamilyID_t preset = FontFamilyIDs::kCount;
PortabilityLayer::FontManager::GetInstance()->GetFontPreset(FontPresets::kSystem12, &preset, nullptr, nullptr, nullptr);
return PortabilityLayer::FontManager::GetInstance()->GetFont(preset);
}
RenderedFont *EditboxWidget::GetRenderedFont() const

View File

@@ -39,7 +39,7 @@ namespace PortabilityLayer
surface->FillRect(m_rect, whiteColor);
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
const Point topLeftCorner = Point::Create(m_rect.left, m_rect.top);
const Point textStartPoint = topLeftCorner + Point::Create(0, sysFont->GetMetrics().m_ascent);

View File

@@ -103,7 +103,7 @@ namespace PortabilityLayer
Rect textRect = innerRect;
textRect.right -= 11;
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, PortabilityLayer::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
Point basePoint = Point::Create(textRect.left + 2, (textRect.top + textRect.bottom + sysFont->GetMetrics().m_ascent + 1) / 2 - 1);
surface->DrawStringConstrained(basePoint, GetString(), textRect, blackColor, sysFont);

View File

@@ -2003,41 +2003,20 @@ void BitMap::Init(const Rect &rect, GpPixelFormat_t pixelFormat, size_t pitch, v
m_data = dataPtr;
}
PortabilityLayer::RenderedFont *GetApplicationFont(int size, int variationFlags, bool aa)
PortabilityLayer::RenderedFont *GetFont(PortabilityLayer::FontPreset_t fontPreset)
{
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetApplicationFont(size, variationFlags);
if (!fontFamily)
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
int size = 0;
int variationFlags = 0;
bool aa = false;
PortabilityLayer::FontFamilyID_t familyID = PortabilityLayer::FontFamilyIDs::kCount;
fontManager->GetFontPreset(fontPreset, &familyID, &size, &variationFlags, &aa);
if (familyID == PortabilityLayer::FontFamilyIDs::kCount)
return nullptr;
return PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, size, aa, variationFlags);
}
PortabilityLayer::RenderedFont *GetSystemFont(int size, int variationFlags, bool aa)
{
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(size, variationFlags);
if (!fontFamily)
return nullptr;
return PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, size, aa, variationFlags);
}
PortabilityLayer::RenderedFont *GetHandwritingFont(int size, int variationFlags, bool aa)
{
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetHandwritingFont(size, variationFlags);
if (!fontFamily)
return nullptr;
return PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, size, aa, variationFlags);
}
PortabilityLayer::RenderedFont *GetMonospaceFont(int size, int variationFlags, bool aa)
{
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetMonospaceFont(size, variationFlags);
if (!fontFamily)
return nullptr;
return PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, size, aa, variationFlags);
return fontManager->GetRenderedFontFromFamily(fontManager->GetFont(familyID), size, aa, variationFlags);
}
#include "stb_image_write.h"

View File

@@ -3,6 +3,7 @@
#include "PLCore.h"
#include "QDGraf.h"
#include "SharedTypes.h"
#include "FontManager.h"
namespace PortabilityLayer
{
@@ -91,10 +92,7 @@ PixMap *GetPortBitMapForCopyBits(DrawSurface *grafPtr);
Boolean SectRect(const Rect *rectA, const Rect *rectB, Rect *outIntersection);
PortabilityLayer::RenderedFont *GetApplicationFont(int size, int variationFlags, bool aa);
PortabilityLayer::RenderedFont *GetSystemFont(int size, int variationFlags, bool aa);
PortabilityLayer::RenderedFont *GetHandwritingFont(int size, int variationFlags, bool aa);
PortabilityLayer::RenderedFont *GetMonospaceFont(int size, int variationFlags, bool aa);
PortabilityLayer::RenderedFont *GetFont(PortabilityLayer::FontPreset_t fontPreset);
inline RGBColor::RGBColor(uint8_t r, uint8_t g, uint8_t b)

View File

@@ -103,6 +103,7 @@
<ClInclude Include="FilePermission.h" />
<ClInclude Include="FileSectionStream.h" />
<ClInclude Include="FontFamily.h" />
<ClInclude Include="FontFamilyID.h" />
<ClInclude Include="FontManager.h" />
<ClInclude Include="FontRenderer.h" />
<ClInclude Include="GpAppInterface.h" />
@@ -151,6 +152,7 @@
<ClInclude Include="PLScrollBarWidget.h" />
<ClInclude Include="PLUnalignedPtr.h" />
<ClInclude Include="PLWidgets.h" />
<ClInclude Include="RenderedFontCatalog.h" />
<ClInclude Include="ResolveCachingColor.h" />
<ClInclude Include="WorkerThread.h" />
<ClInclude Include="TextPlacer.h" />

View File

@@ -426,6 +426,12 @@
<ClInclude Include="InflateStream.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RenderedFontCatalog.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FontFamilyID.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CFileStream.cpp">

View File

@@ -0,0 +1,30 @@
#pragma once
#include "PLBigEndian.h"
namespace PortabilityLayer
{
struct RenderedFontCatalogHeader
{
static const int kVersion = 1;
BEUInt32_t m_version;
BEUInt32_t m_pathsOffset;
BEUInt16_t m_numPaths;
BEUInt16_t m_numRFonts;
};
struct RenderedFontCatalogPathEntry
{
BEUInt16_t m_pathOffset;
BEUInt16_t m_pathSize;
};
struct RenderedFontCatalogRFontEntry
{
uint8_t m_pathIndex;
uint8_t m_hacks;
uint8_t m_fontSize;
uint8_t m_isAA;
};
}

View File

@@ -474,7 +474,7 @@ namespace PortabilityLayer
if (window->GetStyleFlags() & WindowStyleFlags::kCloseBox)
RenderChromeCloseBox(surface, rect, false);
PortabilityLayer::RenderedFont *sysFont = GetSystemFont(12, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *sysFont = GetFont(FontPresets::kSystem12Bold);
int32_t ascender = sysFont->GetMetrics().m_ascent;
const PLPasStr titlePStr = window->GetTitle().ToShortStr();
@@ -593,7 +593,7 @@ namespace PortabilityLayer
if (window->GetStyleFlags() & WindowStyleFlags::kCloseBox)
RenderChromeCloseBox(surface, rect, false);
PortabilityLayer::RenderedFont *appFont = GetApplicationFont(10, PortabilityLayer::FontFamilyFlags::FontFamilyFlag_Bold, true);
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication10Bold);
int32_t ascender = appFont->GetMetrics().m_ascent;
const PLPasStr titlePStr = window->GetTitle().ToShortStr();