Preload entire font file if the font file isn't efficiently seekable, which should fix very slow startup times on Android.

This commit is contained in:
elasota
2020-11-30 18:43:17 -05:00
parent f0b1d6fff9
commit 6851025147
10 changed files with 136 additions and 44 deletions

View File

@@ -166,6 +166,12 @@ bool GpSystemServices_Win32::IsTextInputEnabled() const
return true; return true;
} }
bool GpSystemServices_Win32::AreFontResourcesSeekable() const
{
return true;
}
void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation) void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation)
{ {
m_isTouchscreenSimulation = isTouchscreenSimulation; m_isTouchscreenSimulation = isTouchscreenSimulation;

View File

@@ -35,6 +35,7 @@ public:
unsigned int GetCPUCount() const override; unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override; void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override; bool IsTextInputEnabled() const override;
bool AreFontResourcesSeekable() const override;
void SetTouchscreenSimulation(bool isTouchscreenSimulation); void SetTouchscreenSimulation(bool isTouchscreenSimulation);

View File

@@ -285,6 +285,11 @@ bool GpSystemServices_Android::IsTextInputEnabled() const
return m_textInputEnabled; return m_textInputEnabled;
} }
bool GpSystemServices_Android::AreFontResourcesSeekable() const
{
return false;
}
GpSystemServices_Android *GpSystemServices_Android::GetInstance() GpSystemServices_Android *GpSystemServices_Android::GetInstance()
{ {
return &ms_instance; return &ms_instance;

View File

@@ -23,6 +23,7 @@ public:
unsigned int GetCPUCount() const override; unsigned int GetCPUCount() const override;
void SetTextInputEnabled(bool isEnabled) override; void SetTextInputEnabled(bool isEnabled) override;
bool IsTextInputEnabled() const override; bool IsTextInputEnabled() const override;
bool AreFontResourcesSeekable() const override;
void FlushTextInputEnabled(); void FlushTextInputEnabled();

View File

@@ -11,6 +11,7 @@
#include "Externs.h" #include "Externs.h"
#include "Environ.h" #include "Environ.h"
#include "FontFamily.h" #include "FontFamily.h"
#include "FontManager.h"
#include "GpApplicationName.h" #include "GpApplicationName.h"
#include "GpRenderedFontMetrics.h" #include "GpRenderedFontMetrics.h"
#include "IGpMutex.h" #include "IGpMutex.h"
@@ -672,7 +673,6 @@ void PreloadFonts()
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
const int numFontSpecs = sizeof(specs) / sizeof(specs[0]); const int numFontSpecs = sizeof(specs) / sizeof(specs[0]);
int queuedSpecs = 0; int queuedSpecs = 0;
@@ -714,6 +714,8 @@ void PreloadFonts()
StepLoadScreenRing(); StepLoadScreenRing();
Delay(1, nullptr); Delay(1, nullptr);
} }
PortabilityLayer::FontManager::GetInstance()->PurgeCache();
} }
struct PreloadAATableSpec struct PreloadAATableSpec

View File

@@ -33,4 +33,5 @@ public:
virtual unsigned int GetCPUCount() const = 0; virtual unsigned int GetCPUCount() const = 0;
virtual void SetTextInputEnabled(bool isEnabled) = 0; virtual void SetTextInputEnabled(bool isEnabled) = 0;
virtual bool IsTextInputEnabled() const = 0; virtual bool IsTextInputEnabled() const = 0;
virtual bool AreFontResourcesSeekable() const = 0;
}; };

View File

@@ -3,7 +3,10 @@
#include "IGpFileSystem.h" #include "IGpFileSystem.h"
#include "IGpFontHandler.h" #include "IGpFontHandler.h"
#include "IGpFont.h" #include "IGpFont.h"
#include "IGpSystemServices.h"
#include "MemReaderStream.h"
#include "MemoryManager.h"
#include "PLDrivers.h" #include "PLDrivers.h"
#include <stdlib.h> #include <stdlib.h>
@@ -11,11 +14,82 @@
namespace PortabilityLayer namespace PortabilityLayer
{ {
FontFamily::FontSpec::FontSpec()
: m_fontPath(nullptr)
, m_font(nullptr)
, m_hacks(FontHacks_None)
, m_isRegistered(false)
{
}
void FontFamily::AddFont(int flags, const char *path, FontHacks fontHacks) void FontFamily::AddFont(int flags, const char *path, FontHacks fontHacks)
{ {
GpIOStream *sysFontStream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFonts, path, false, GpFileCreationDispositions::kOpenExisting); m_fontSpecs[flags].m_fontPath = path;
m_fontSpecs[flags].m_hacks = fontHacks;
m_fontSpecs[flags].m_isRegistered = true;
if (!m_fontSpecs[0].m_isRegistered)
m_defaultVariation = flags;
}
void FontFamily::SetDefaultVariation(int defaultVariation)
{
if (m_fontSpecs[defaultVariation].m_isRegistered)
m_defaultVariation = defaultVariation;
}
int FontFamily::GetVariationForFlags(int variation) const
{
if (m_fontSpecs[variation].m_isRegistered)
return variation;
if (m_fontSpecs[0].m_isRegistered)
return 0;
return m_defaultVariation;
}
IGpFont *FontFamily::GetFontForVariation(int variation)
{
FontSpec &spec = m_fontSpecs[variation];
if (spec.m_font)
return spec.m_font;
GpIOStream *sysFontStream = PLDrivers::GetFileSystem()->OpenFile(PortabilityLayer::VirtualDirectories::kFonts, spec.m_fontPath, false, GpFileCreationDispositions::kOpenExisting);
if (!sysFontStream) if (!sysFontStream)
return; return nullptr;
if (!PLDrivers::GetSystemServices()->AreFontResourcesSeekable())
{
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
size_t fontSize = sysFontStream->Size();
void *buffer = mm->Alloc(fontSize);
if (!buffer)
{
sysFontStream->Close();
return nullptr;
}
MemBufferReaderStream *bufferStream = MemBufferReaderStream::Create(buffer, fontSize);
if (!bufferStream)
{
mm->Release(buffer);
sysFontStream->Close();
return nullptr;
}
if (sysFontStream->Read(buffer, fontSize) != fontSize)
{
mm->Release(buffer);
sysFontStream->Close();
return nullptr;
}
sysFontStream->Close();
sysFontStream = bufferStream;
}
IGpFontHandler *fontHandler = PLDrivers::GetFontHandler(); IGpFontHandler *fontHandler = PLDrivers::GetFontHandler();
@@ -25,40 +99,16 @@ namespace PortabilityLayer
sysFontStream->Close(); sysFontStream->Close();
if (!font) if (!font)
return; return nullptr;
m_fonts[flags] = font; spec.m_font = font;
m_hacks[flags] = fontHacks;
if (m_fonts[0] == nullptr) return font;
m_defaultVariation = flags;
}
void FontFamily::SetDefaultVariation(int defaultVariation)
{
if (m_fonts[defaultVariation])
m_defaultVariation = defaultVariation;
}
int FontFamily::GetVariationForFlags(int variation) const
{
if (m_fonts[variation])
return variation;
if (m_fonts[0])
return 0;
return m_defaultVariation;
}
IGpFont *FontFamily::GetFontForVariation(int variation) const
{
return m_fonts[variation];
} }
PortabilityLayer::FontHacks FontFamily::GetHacksForVariation(int variation) const PortabilityLayer::FontHacks FontFamily::GetHacksForVariation(int variation) const
{ {
return m_hacks[variation]; return m_fontSpecs[variation].m_hacks;
} }
int FontFamily::GetCacheID() const int FontFamily::GetCacheID() const
@@ -66,6 +116,18 @@ namespace PortabilityLayer
return m_cacheID; return m_cacheID;
} }
void FontFamily::PurgeCache()
{
for (unsigned int i = 0; i < kNumVariations; i++)
{
if (IGpFont *font = m_fontSpecs[i].m_font)
{
font->Destroy();
m_fontSpecs[i].m_font = nullptr;
}
}
}
FontFamily *FontFamily::Create(int cacheID) FontFamily *FontFamily::Create(int cacheID)
{ {
void *storage = malloc(sizeof(FontFamily)); void *storage = malloc(sizeof(FontFamily));
@@ -85,19 +147,10 @@ namespace PortabilityLayer
: m_defaultVariation(0) : m_defaultVariation(0)
, m_cacheID(cacheID) , m_cacheID(cacheID)
{ {
for (unsigned int i = 0; i < kNumVariations; i++)
{
m_fonts[i] = nullptr;
m_hacks[i] = FontHacks_None;
}
} }
FontFamily::~FontFamily() FontFamily::~FontFamily()
{ {
for (unsigned int i = 0; i < kNumVariations; i++) PurgeCache();
{
if (IGpFont *font = m_fonts[i])
font->Destroy();
}
} }
} }

View File

@@ -26,17 +26,28 @@ namespace PortabilityLayer
void SetDefaultVariation(int defaultVariation); void SetDefaultVariation(int defaultVariation);
int GetVariationForFlags(int variation) const; int GetVariationForFlags(int variation) const;
IGpFont *GetFontForVariation(int variation) const; IGpFont *GetFontForVariation(int variation);
FontHacks GetHacksForVariation(int variation) const; FontHacks GetHacksForVariation(int variation) const;
int GetCacheID() const; int GetCacheID() const;
void PurgeCache();
static FontFamily *Create(int cacheID); static FontFamily *Create(int cacheID);
void Destroy(); void Destroy();
private: private:
FontHacks m_hacks[kNumVariations]; struct FontSpec
IGpFont *m_fonts[kNumVariations]; {
FontSpec();
IGpFont *m_font;
FontHacks m_hacks;
const char *m_fontPath;
bool m_isRegistered;
};
FontSpec m_fontSpecs[kNumVariations];
uint8_t m_defaultVariation; uint8_t m_defaultVariation;
int m_cacheID; int m_cacheID;

View File

@@ -35,6 +35,8 @@ namespace PortabilityLayer
RenderedFont *LoadCachedRenderedFont(int cacheID, int size, bool aa, int flags) const 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; void SaveCachedRenderedFont(const RenderedFont *rfont, int cacheID, int size, bool aa, int flags) const override;
void PurgeCache() override;
static FontManagerImpl *GetInstance(); static FontManagerImpl *GetInstance();
private: private:
@@ -264,6 +266,14 @@ namespace PortabilityLayer
stream->Close(); stream->Close();
} }
void FontManagerImpl::PurgeCache()
{
m_systemFont->PurgeCache();
m_applicationFont->PurgeCache();
m_handwritingFont->PurgeCache();
m_monospaceFont->PurgeCache();
}
FontManagerImpl *FontManagerImpl::GetInstance() FontManagerImpl *FontManagerImpl::GetInstance()
{ {
return &ms_instance; return &ms_instance;

View File

@@ -26,6 +26,8 @@ namespace PortabilityLayer
virtual RenderedFont *LoadCachedRenderedFont(int cacheID, int size, bool aa, int flags) const = 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 void SaveCachedRenderedFont(const RenderedFont *rfont, int cacheID, int size, bool aa, int flags) const = 0;
virtual void PurgeCache() = 0;
static FontManager *GetInstance(); static FontManager *GetInstance();
}; };
} }