From 68510251477b5a22f9156cb07d86e606e6102364 Mon Sep 17 00:00:00 2001 From: elasota Date: Mon, 30 Nov 2020 18:43:17 -0500 Subject: [PATCH] Preload entire font file if the font file isn't efficiently seekable, which should fix very slow startup times on Android. --- Aerofoil/GpSystemServices_Win32.cpp | 6 + Aerofoil/GpSystemServices_Win32.h | 1 + .../app/jni/main/GpSystemServices_Android.cpp | 5 + .../app/jni/main/GpSystemServices_Android.h | 1 + GpApp/Main.cpp | 4 +- GpCommon/IGpSystemServices.h | 1 + PortabilityLayer/FontFamily.cpp | 133 ++++++++++++------ PortabilityLayer/FontFamily.h | 17 ++- PortabilityLayer/FontManager.cpp | 10 ++ PortabilityLayer/FontManager.h | 2 + 10 files changed, 136 insertions(+), 44 deletions(-) diff --git a/Aerofoil/GpSystemServices_Win32.cpp b/Aerofoil/GpSystemServices_Win32.cpp index 1da5a3d..ec40190 100644 --- a/Aerofoil/GpSystemServices_Win32.cpp +++ b/Aerofoil/GpSystemServices_Win32.cpp @@ -166,6 +166,12 @@ bool GpSystemServices_Win32::IsTextInputEnabled() const return true; } +bool GpSystemServices_Win32::AreFontResourcesSeekable() const +{ + return true; +} + + void GpSystemServices_Win32::SetTouchscreenSimulation(bool isTouchscreenSimulation) { m_isTouchscreenSimulation = isTouchscreenSimulation; diff --git a/Aerofoil/GpSystemServices_Win32.h b/Aerofoil/GpSystemServices_Win32.h index e48c263..dbcb5bc 100644 --- a/Aerofoil/GpSystemServices_Win32.h +++ b/Aerofoil/GpSystemServices_Win32.h @@ -35,6 +35,7 @@ public: unsigned int GetCPUCount() const override; void SetTextInputEnabled(bool isEnabled) override; bool IsTextInputEnabled() const override; + bool AreFontResourcesSeekable() const override; void SetTouchscreenSimulation(bool isTouchscreenSimulation); diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp index f7083ee..5e16b4b 100644 --- a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.cpp @@ -285,6 +285,11 @@ bool GpSystemServices_Android::IsTextInputEnabled() const return m_textInputEnabled; } +bool GpSystemServices_Android::AreFontResourcesSeekable() const +{ + return false; +} + GpSystemServices_Android *GpSystemServices_Android::GetInstance() { return &ms_instance; diff --git a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h index 52bc820..93b44c5 100644 --- a/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h +++ b/AerofoilAndroid/app/jni/main/GpSystemServices_Android.h @@ -23,6 +23,7 @@ public: unsigned int GetCPUCount() const override; void SetTextInputEnabled(bool isEnabled) override; bool IsTextInputEnabled() const override; + bool AreFontResourcesSeekable() const override; void FlushTextInputEnabled(); diff --git a/GpApp/Main.cpp b/GpApp/Main.cpp index bb0164a..12f4d6f 100644 --- a/GpApp/Main.cpp +++ b/GpApp/Main.cpp @@ -11,6 +11,7 @@ #include "Externs.h" #include "Environ.h" #include "FontFamily.h" +#include "FontManager.h" #include "GpApplicationName.h" #include "GpRenderedFontMetrics.h" #include "IGpMutex.h" @@ -672,7 +673,6 @@ void PreloadFonts() PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance(); - const int numFontSpecs = sizeof(specs) / sizeof(specs[0]); int queuedSpecs = 0; @@ -714,6 +714,8 @@ void PreloadFonts() StepLoadScreenRing(); Delay(1, nullptr); } + + PortabilityLayer::FontManager::GetInstance()->PurgeCache(); } struct PreloadAATableSpec diff --git a/GpCommon/IGpSystemServices.h b/GpCommon/IGpSystemServices.h index a9f0d2c..5327afa 100644 --- a/GpCommon/IGpSystemServices.h +++ b/GpCommon/IGpSystemServices.h @@ -33,4 +33,5 @@ public: virtual unsigned int GetCPUCount() const = 0; virtual void SetTextInputEnabled(bool isEnabled) = 0; virtual bool IsTextInputEnabled() const = 0; + virtual bool AreFontResourcesSeekable() const = 0; }; diff --git a/PortabilityLayer/FontFamily.cpp b/PortabilityLayer/FontFamily.cpp index 78cd4a6..dba7a1b 100644 --- a/PortabilityLayer/FontFamily.cpp +++ b/PortabilityLayer/FontFamily.cpp @@ -3,7 +3,10 @@ #include "IGpFileSystem.h" #include "IGpFontHandler.h" #include "IGpFont.h" +#include "IGpSystemServices.h" +#include "MemReaderStream.h" +#include "MemoryManager.h" #include "PLDrivers.h" #include @@ -11,11 +14,82 @@ 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) { - 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) - 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(); @@ -25,40 +99,16 @@ namespace PortabilityLayer sysFontStream->Close(); if (!font) - return; + return nullptr; - m_fonts[flags] = font; - m_hacks[flags] = fontHacks; + spec.m_font = font; - if (m_fonts[0] == nullptr) - 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]; + return font; } PortabilityLayer::FontHacks FontFamily::GetHacksForVariation(int variation) const { - return m_hacks[variation]; + return m_fontSpecs[variation].m_hacks; } int FontFamily::GetCacheID() const @@ -66,6 +116,18 @@ namespace PortabilityLayer 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) { void *storage = malloc(sizeof(FontFamily)); @@ -85,19 +147,10 @@ namespace PortabilityLayer : m_defaultVariation(0) , m_cacheID(cacheID) { - for (unsigned int i = 0; i < kNumVariations; i++) - { - m_fonts[i] = nullptr; - m_hacks[i] = FontHacks_None; - } } FontFamily::~FontFamily() { - for (unsigned int i = 0; i < kNumVariations; i++) - { - if (IGpFont *font = m_fonts[i]) - font->Destroy(); - } + PurgeCache(); } } diff --git a/PortabilityLayer/FontFamily.h b/PortabilityLayer/FontFamily.h index 6c7a25c..88e1283 100644 --- a/PortabilityLayer/FontFamily.h +++ b/PortabilityLayer/FontFamily.h @@ -26,17 +26,28 @@ namespace PortabilityLayer void SetDefaultVariation(int defaultVariation); int GetVariationForFlags(int variation) const; - IGpFont *GetFontForVariation(int variation) const; + IGpFont *GetFontForVariation(int variation); FontHacks GetHacksForVariation(int variation) const; int GetCacheID() const; + void PurgeCache(); + static FontFamily *Create(int cacheID); void Destroy(); private: - FontHacks m_hacks[kNumVariations]; - IGpFont *m_fonts[kNumVariations]; + struct FontSpec + { + FontSpec(); + + IGpFont *m_font; + FontHacks m_hacks; + const char *m_fontPath; + bool m_isRegistered; + }; + + FontSpec m_fontSpecs[kNumVariations]; uint8_t m_defaultVariation; int m_cacheID; diff --git a/PortabilityLayer/FontManager.cpp b/PortabilityLayer/FontManager.cpp index d87007e..c7c1845 100644 --- a/PortabilityLayer/FontManager.cpp +++ b/PortabilityLayer/FontManager.cpp @@ -35,6 +35,8 @@ namespace PortabilityLayer 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 PurgeCache() override; + static FontManagerImpl *GetInstance(); private: @@ -264,6 +266,14 @@ namespace PortabilityLayer stream->Close(); } + void FontManagerImpl::PurgeCache() + { + m_systemFont->PurgeCache(); + m_applicationFont->PurgeCache(); + m_handwritingFont->PurgeCache(); + m_monospaceFont->PurgeCache(); + } + FontManagerImpl *FontManagerImpl::GetInstance() { return &ms_instance; diff --git a/PortabilityLayer/FontManager.h b/PortabilityLayer/FontManager.h index c91d3e7..485646f 100644 --- a/PortabilityLayer/FontManager.h +++ b/PortabilityLayer/FontManager.h @@ -26,6 +26,8 @@ namespace PortabilityLayer 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 PurgeCache() = 0; + static FontManager *GetInstance(); }; }