migrate fonts to scoped resource ownership

- replace FontManager with per-ResourceScope FontService instances
  - publish font factories into explicit or default resource scopes
  - import default resources into UI scene scopes unless explicitly disabled
  - keep related font faces strongly owned without hot-path weak_ptr locking
  - add cached glyph advance queries without creating texture pages
  - fix font picker preview ownership, cleanup, and rapid switching
  - selectively evict TextLayout cache entries when referenced fonts unload
  - document FontService, ResourceCatalog, and cache invalidation semantics
  - migrate examples, tools, benchmarks, and tests to the scoped font API
  - expand coverage for font ownership, texture release, and layout caching
This commit is contained in:
Martín Lucas Golini
2026-07-24 01:54:51 -03:00
parent 24531b4411
commit 6b277e508b
83 changed files with 1940 additions and 828 deletions
@@ -233,9 +233,11 @@ Frozen lookup rules:
- Never search the live registry.
- Never implicitly search a parent, host scene, sibling scene, or every live resource.
- The default Graphics scope imports the global catalog explicitly.
- A UI/application scene receives only the catalogs deliberately imported into it.
- A Web document does not inherit host/global resources unless the host exports and imports them
intentionally.
- A UI/application scene imports the default resource catalog automatically for the common case;
callers can disable this at construction for strict isolation and then import only the catalogs
they deliberately expose.
- A Web document receives the same default-catalog baseline unless created with automatic import
disabled. It never implicitly inherits host, sibling, or other document-local catalogs.
- Scopes import catalogs, not arbitrary scopes. This avoids recursive lookup and import cycles.
Pure `EE::Graphics` users may use TextureFactory for unpinned creation or Engine's default Graphics
@@ -566,7 +568,7 @@ focused regression coverage while preserving current raw factory ownership:
- Externally executed HTTP tasks cannot retain a dangling raw Http after Pool destruction.
- TextureAtlasLoader joins/stops ResourceLoader work before callback-visible loader state is
destroyed.
- Engine destroys ShaderProgramManager before Renderer and clears TextLayout before FontManager.
- Engine clears TextLayout before destroying the default ResourceScope and its FontService.
- Engine stops asynchronous resource producers before resource consumers and GPU managers.
- UISceneNode's static async delivery queue has an explicit shutdown purge/rejection boundary.
- Obsolete FrameBuffer context-loss reload APIs were removed.
@@ -808,6 +810,17 @@ raw-owning ResourceManager subclass one family at a time. Their self-contained G
the established graphics-thread destruction contract unless a concrete migration requires
otherwise.
For fonts, ownership is separate from rendering policy. Font handles and semantic lookup live in
naturally owned catalogs: application defaults use the default scope, while author `@font-face`
resources are owned by their document scene. Every `ResourceScope` owns an inline `FontService` for
its rendering configuration, emoji fonts, configured fallbacks, and system fallback cache. Fonts
retain only a borrowed service pointer while published in that scope and are detached when removed
or when the scope is destroyed. Raw `Font*` values in text/layout/style structures remain borrowed
views whose enclosing application, scene, theme, or fallback service retains the corresponding
handle. The former process-wide `FontManager` singleton and compatibility namespace were removed.
Publishing a font with an existing local key replaces that catalog binding; the legacy manager
behavior that silently suffixed duplicate font names is intentionally not preserved.
Remove raw-owning `ResourceManager<T>` only when no subclass or consumer depends on it.
## 11. Required validation matrix
@@ -873,8 +886,8 @@ Remove raw-owning `ResourceManager<T>` only when no subclass or consumer depends
## 12. Next implementation deliverable
Stage 7 continues with the remaining ResourceManager families one at a time: fonts and font caches,
themes/icons, shaders/programs, and any remaining raw-owning manager. Each singleton semantic
namespace is replaced by naturally owned catalogs plus explicit scope imports, following the
completed nine-patch and texture-atlas migrations. The raw-owning ResourceManager template is
removed only after its final consumer is migrated.
Stage 7 continues with the remaining ResourceManager families one at a time. Fonts and font caches
now use scope catalogs plus `FontService`; the next families are themes/icons, shaders/programs, and
any remaining raw-owning manager. Each singleton semantic namespace is replaced by naturally owned
catalogs plus explicit scope imports. The raw-owning ResourceManager template is removed only after
its final consumer is migrated.
+27
View File
@@ -68,6 +68,17 @@ class DynamicLRU {
mCacheMap.clear();
}
template <typename Predicate> void eraseIf( Predicate predicate ) {
for ( auto it = mCacheList.begin(); it != mCacheList.end(); ) {
if ( predicate( it->first, it->second ) ) {
mCacheMap.erase( it->first );
it = mCacheList.erase( it );
} else {
++it;
}
}
}
[[nodiscard]] std::size_t size() const { return mCacheList.size(); }
};
@@ -166,6 +177,19 @@ class StaticLRU {
used_ = 0;
}
template <typename Predicate> void eraseIf( Predicate predicate ) {
std::vector<std::pair<KeyT, ValueT>> retained;
retained.reserve( used_ );
for ( std::uint16_t idx = head_; idx < N; idx = next_[idx] ) {
if ( !predicate( keys_[idx], vals_[idx] ) )
retained.emplace_back( std::move( keys_[idx] ), std::move( vals_[idx] ) );
}
clear();
for ( auto it = retained.rbegin(); it != retained.rend(); ++it )
put( std::move( it->first ), std::move( it->second ) );
}
[[nodiscard]] std::size_t size() const noexcept { return used_; }
private:
@@ -283,6 +307,9 @@ class LRUCache {
std::optional<ValueT> get( KeyParamT key ) { return impl_.get( key ); }
void put( KeyT key, ValueT value ) { impl_.put( std::move( key ), std::move( value ) ); }
void clear() { impl_.clear(); }
template <typename Predicate> void eraseIf( Predicate predicate ) {
impl_.eraseIf( std::move( predicate ) );
}
static constexpr std::size_t capacity() { return Capacity; }
[[nodiscard]] std::size_t size() const { return impl_.size(); }
+3 -3
View File
@@ -13,7 +13,7 @@
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontbmfont.hpp>
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fontsprite.hpp>
#include <eepp/graphics/fontstyleconfig.hpp>
#include <eepp/graphics/fonttruetype.hpp>
@@ -43,9 +43,9 @@
#include <eepp/graphics/renderer/rendererglshader.hpp>
#include <eepp/graphics/renderer/rendererhelper.hpp>
#include <eepp/graphics/rendermode.hpp>
#include <eepp/graphics/richtext.hpp>
#include <eepp/graphics/resourcecatalog.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/richtext.hpp>
#include <eepp/graphics/scopedtexture.hpp>
#include <eepp/graphics/scrollparallax.hpp>
#include <eepp/graphics/shader.hpp>
@@ -62,9 +62,9 @@
#include <eepp/graphics/textshaperun.hpp>
#include <eepp/graphics/texttransform.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/texturedrawable.hpp>
#include <eepp/graphics/textureatlas.hpp>
#include <eepp/graphics/textureatlasloader.hpp>
#include <eepp/graphics/texturedrawable.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/textureloader.hpp>
#include <eepp/graphics/texturepacker.hpp>
+6
View File
@@ -11,6 +11,8 @@ using namespace std::literals;
namespace EE { namespace Graphics {
class Font;
using FontPtr = ResourcePtr<Font>;
using FontWeakPtr = ResourceWeakPtr<Font>;
struct EE_API Glyph {
Float advance{ 0 }; ///< Offset to move horizontally to the next character
@@ -135,6 +137,10 @@ class EE_API Font {
virtual Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const = 0;
/** Returns the horizontal advance without requiring a renderable glyph texture. */
virtual Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
/** @return The glyph drawable that represents the glyph in a texture. The glyph drawable
* allocation is managed by the font. */
virtual GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
+13 -2
View File
@@ -12,12 +12,20 @@ class IOStream;
namespace EE { namespace Graphics {
class FontBMFont;
class ResourceScope;
using FontBMFontPtr = ResourcePtr<FontBMFont>;
using FontBMFontWeakPtr = ResourceWeakPtr<FontBMFont>;
/** @brief Implementation of AngelCode BMFont fonts. */
class EE_API FontBMFont : public Font {
public:
static FontBMFont* New( const std::string fontName );
static FontBMFontPtr New( const std::string fontName );
static FontBMFontPtr New( const std::string fontName, ResourceScope& resourceScope );
static FontBMFont* New( const std::string fontName, const std::string& filename );
static FontBMFontPtr New( const std::string fontName, const std::string& filename );
static FontBMFontPtr New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope );
~FontBMFont();
@@ -39,6 +47,9 @@ class EE_API FontBMFont : public Font {
Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
GlyphDrawable* getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
bool bold = false, bool italic = false,
Float outlineThickness = 0 ) const;
+2 -2
View File
@@ -14,8 +14,8 @@ class EE_API FontFamily {
const std::string& ext,
const std::vector<std::string_view>& names );
static FontTrueType* setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType );
static void setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType );
};
}} // namespace EE::Graphics
-70
View File
@@ -1,70 +0,0 @@
#ifndef EE_GRAPHICSCFONTMANAGER_HPP
#define EE_GRAPHICSCFONTMANAGER_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/system/resourcemanager.hpp>
#include <eepp/system/singleton.hpp>
using namespace EE::System;
namespace EE { namespace Graphics {
class FontTrueType;
struct FontDesc;
/** @brief The Font Manager is a singleton class that manages all the instance of fonts
instantiated. And releases the font instances automatically. So the user doesn't need to release
any font instance.
*/
class EE_API FontManager : public ResourceManager<Font> {
SINGLETON_DECLARE_HEADERS( FontManager )
public:
virtual ~FontManager();
/** @brief Adds a new font to the manager */
Graphics::Font* add( Graphics::Font* Font );
Font* getColorEmojiFont() const;
void setColorEmojiFont( Graphics::Font* font );
Font* getEmojiFont() const;
void setEmojiFont( Font* newEmojiFont );
const std::vector<Font*>& getFallbackFonts() const;
bool hasFallbackFonts() const;
bool addFallbackFont( Font* fallbackFont );
bool removeFallbackFont( Font* fallbackFont );
FontHinting getHinting() const;
void setHinting( FontHinting hinting );
FontAntialiasing getAntialiasing() const;
void setAntialiasing( FontAntialiasing antialiasing );
Font* getByInternalId( Uint32 internalId ) const;
FontTrueType* getOrLoadSystemFallbackFont( const FontDesc& desc );
protected:
Font* mColorEmojiFont{ nullptr };
Font* mEmojiFont{ nullptr };
std::vector<Font*> mFallbackFonts;
std::vector<Font*> mSystemFallbackFonts;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
FontManager();
};
}} // namespace EE::Graphics
#endif
+135
View File
@@ -0,0 +1,135 @@
#ifndef EE_GRAPHICS_FONTSERVICE_HPP
#define EE_GRAPHICS_FONTSERVICE_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
namespace EE { namespace Graphics {
class FontTrueType;
class ResourceScope;
struct FontDesc;
/**
* @brief Owns font fallback state and rendering policy for a ResourceScope.
*
* Every ResourceScope has one FontService. Fonts published locally by that scope are associated
* with its service, allowing glyph lookup to resolve configured emoji, explicit fallback, and
* system fallback fonts without consulting global state.
*
* The service strongly owns configured emoji and fallback fonts. Raw-pointer setters only accept
* fonts that can be resolved through the associated scope; passing an unrelated pointer clears or
* ignores the corresponding configuration. Removing a locally published font from the scope also
* removes any service references to it.
*
* Rendering policy changes are applied to TrueType fonts associated with this service. Imported
* fonts remain associated with the service of their owning scope and are therefore not mutated.
*
* System fonts can be loaded with two different lifetime contracts:
* - loadSystemFont() returns an independently owned, uncached font.
* - getOrLoadSystemFallbackFont() retains the font in this service for repeated fallback lookup.
*/
class EE_API FontService {
friend class ResourceScope;
public:
/** Creates a service associated with @p resourceScope. ResourceScope owns its service. */
explicit FontService( ResourceScope& resourceScope );
/** @return The resource scope whose fonts and policy are managed by this service. */
ResourceScope& getResourceScope() const;
/** @return The configured color emoji font, or nullptr when none is configured. */
Font* getColorEmojiFont() const;
/**
* Sets the color emoji font. The font must be resolvable through the associated scope. Passing
* nullptr or an unrelated font clears the current value.
*/
void setColorEmojiFont( Font* font );
/** @return The configured monochrome emoji font, or nullptr when none is configured. */
Font* getEmojiFont() const;
/**
* Sets the monochrome emoji font. The font must be resolvable through the associated scope.
* Passing nullptr or an unrelated font clears the current value.
*/
void setEmojiFont( Font* font );
/** @return The strongly owned explicit fallback fonts in lookup order. */
const std::vector<FontPtr>& getFallbackFonts() const;
/** @return Whether at least one explicit fallback font is configured. */
bool hasFallbackFonts() const;
/** Adds an owning fallback handle unless the same font is already configured. */
bool addFallbackFont( FontPtr fallbackFont );
/**
* Adds a fallback font resolved through the associated scope.
* @return True when the font was found and added; false otherwise.
*/
bool addFallbackFont( Font* fallbackFont );
/** Removes the matching explicit fallback font without removing it from its resource scope. */
bool removeFallbackFont( Font* fallbackFont );
/** @return The policy used when loading and updating associated TrueType fonts. */
FontHinting getHinting() const;
/** Updates the hinting policy and applies it to associated non-emoji TrueType fonts. */
void setHinting( FontHinting hinting );
/** @return The antialiasing policy used by associated TrueType fonts. */
FontAntialiasing getAntialiasing() const;
/** Updates the antialiasing policy and applies it to associated non-emoji TrueType fonts. */
void setAntialiasing( FontAntialiasing antialiasing );
/**
* Finds a TrueType font visible through the associated scope by its runtime internal ID.
* @return A borrowed pointer, or nullptr when no matching font is visible.
*/
Font* getByInternalId( Uint32 internalId ) const;
/**
* Loads a standalone system font described by @p desc.
*
* The font is not published into the associated scope and is not retained by this service. The
* returned handle is its sole owner and can be released independently, immediately freeing its
* glyph pages when no other handle exists. Current hinting and antialiasing policy is applied
* at load time. The standalone font does not use this service for subsequent fallback
* resolution.
*
* @return An owning handle, or an empty handle when the descriptor cannot be loaded.
*/
ResourcePtr<FontTrueType> loadSystemFont( const FontDesc& desc );
/**
* Finds or loads a system fallback font described by @p desc.
*
* Successfully loaded fonts are published into the associated scope and strongly retained by
* the service for future glyph fallback requests. The returned pointer is borrowed and remains
* valid until the font is removed from the scope or the service is destroyed.
*
* @return A borrowed pointer to the cached font, or nullptr when loading fails.
*/
FontTrueType* getOrLoadSystemFallbackFont( const FontDesc& desc );
private:
FontPtr findHandle( Font* font ) const;
void onFontRemoved( Font* font );
ResourceScope& mResourceScope;
FontPtr mColorEmojiFont;
FontPtr mEmojiFont;
std::vector<FontPtr> mFallbackFonts;
std::vector<FontPtr> mSystemFallbackFonts;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
};
}} // namespace EE::Graphics
#endif
+10 -2
View File
@@ -13,12 +13,20 @@ class IOStream;
namespace EE { namespace Graphics {
class FontSprite;
class ResourceScope;
using FontSpritePtr = ResourcePtr<FontSprite>;
using FontSpriteWeakPtr = ResourceWeakPtr<FontSprite>;
/** @brief Implementation of XNA Font Sprites */
class EE_API FontSprite : public Font {
public:
static FontSprite* New( const std::string fontName );
static FontSpritePtr New( const std::string fontName );
static FontSpritePtr New( const std::string fontName, ResourceScope& resourceScope );
static FontSprite* New( const std::string fontName, const std::string& filename );
static FontSpritePtr New( const std::string fontName, const std::string& filename );
static FontSpritePtr New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope );
~FontSprite();
+35 -24
View File
@@ -15,15 +15,26 @@ namespace EE { namespace Graphics {
enum class FontWeight : Uint16;
struct FontDesc;
class ResourceScope;
class FontTrueType;
class FontService;
using FontTrueTypePtr = ResourcePtr<FontTrueType>;
using FontTrueTypeWeakPtr = ResourceWeakPtr<FontTrueType>;
class EE_API FontTrueType : public Font {
public:
static FontTrueType* New( const std::string& FontName );
static FontTrueTypePtr New( const std::string& FontName );
static FontTrueTypePtr New( const std::string& FontName, ResourceScope& resourceScope );
static FontTrueType* New( const std::string& FontName, const std::string& filename );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
ResourceScope& resourceScope );
static FontTrueType* New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex );
static FontTrueTypePtr New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex, ResourceScope& resourceScope );
~FontTrueType();
@@ -48,6 +59,9 @@ class EE_API FontTrueType : public Font {
Glyph getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
Glyph getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness = 0 ) const;
@@ -80,6 +94,7 @@ class EE_API FontTrueType : public Font {
const TexturePtr& getTexture( unsigned int characterSize ) const;
bool loaded() const;
FontService* getFontService() const;
FontTrueType( const FontTrueType& ) = delete;
FontTrueType& operator=( const FontTrueType& ) = delete;
@@ -151,19 +166,19 @@ class EE_API FontTrueType : public Font {
virtual bool hasItalic() const { return mIsItalic || mFontItalic != nullptr; }
virtual bool hasBoldItalic() const { return isBoldItalic() || mFontBoldItalic; }
virtual bool hasBoldItalic() const { return isBoldItalic() || mFontBoldItalic != nullptr; }
FontTrueType* getBoldFont() const { return mFontBold; }
const FontTrueTypePtr& getBoldFont() const { return mFontBold; }
FontTrueType* getItalicFont() const { return mFontItalic; }
const FontTrueTypePtr& getItalicFont() const { return mFontItalic; }
FontTrueType* getBoldItalicFont() const { return mFontBoldItalic; }
const FontTrueTypePtr& getBoldItalicFont() const { return mFontBoldItalic; }
void setBoldFont( FontTrueType* fontBold );
void setBoldFont( const FontTrueTypePtr& fontBold );
void setItalicFont( FontTrueType* fontItalic );
void setItalicFont( const FontTrueTypePtr& fontItalic );
void setBoldItalicFont( FontTrueType* fontBoldItalic );
void setBoldItalicFont( const FontTrueTypePtr& fontBoldItalic );
void* face() const { return mFace; }
@@ -178,8 +193,11 @@ class EE_API FontTrueType : public Font {
protected:
friend class Text;
friend class TextLayout;
friend class FontService;
friend class ResourceScope;
explicit FontTrueType( const std::string& FontName );
explicit FontTrueType( const std::string& FontName, FontService& fontService );
void setFontService( FontService* fontService );
struct Row {
Row( unsigned int rowTop, unsigned int rowHeight ) :
@@ -267,15 +285,14 @@ class EE_API FontTrueType : public Font {
mutable UnorderedMap<Uint32, std::tuple<Uint32, Uint32, bool>> mKeyCache;
mutable UnorderedMap<Uint64, Float> mKerningCache; // For codepoints (getKerning)
mutable UnorderedMap<Uint64, Float> mKerningGlyphCache; // For glyph indices
mutable UnorderedMap<unsigned int, UnorderedMap<Uint64, Float>> mGlyphAdvanceCache;
FontHinting mHinting{ FontHinting::Full };
FontAntialiasing mAntialiasing{ FontAntialiasing::Grayscale };
FontService* mFontService{ nullptr };
Uint32 mFaceIndex{ 0 };
FontTrueType* mFontBold{ nullptr };
FontTrueType* mFontItalic{ nullptr };
FontTrueType* mFontBoldItalic{ nullptr };
Uint32 mFontBoldCb{ 0 };
Uint32 mFontItalicCb{ 0 };
Uint32 mFontBoldItalicCb{ 0 };
FontTrueTypePtr mFontBold;
FontTrueTypePtr mFontItalic;
FontTrueTypePtr mFontBoldItalic;
Float getGlyphTopOffset( unsigned int characterSize ) const;
@@ -284,12 +301,6 @@ class EE_API FontTrueType : public Font {
bool setFontFace( void* face );
void updateMonospaceState() const;
void disconnectBoldFont();
void disconnectItalicFont();
void disconnectBoldItalicFont();
};
}} // namespace EE::Graphics
+11
View File
@@ -1,6 +1,7 @@
#ifndef EE_GRAPHICS_RESOURCE_HPP
#define EE_GRAPHICS_RESOURCE_HPP
#include <functional>
#include <memory>
#include <string>
#include <utility>
@@ -57,4 +58,14 @@ template <typename T, typename... Args> ResourcePtr<T> makeResource( Args&&... a
}} // namespace EE::Graphics
namespace std {
template <> struct hash<EE::Graphics::ResourceId> {
std::size_t operator()( const EE::Graphics::ResourceId& id ) const noexcept {
return std::hash<EE::Uint64>{}( id.value() );
}
};
} // namespace std
#endif
+93 -1
View File
@@ -3,6 +3,7 @@
#include <eepp/core/containers.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/resource.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/textureatlas.hpp>
@@ -13,34 +14,123 @@ namespace EE { namespace Graphics {
class ResourceCatalog;
using ResourceCatalogPtr = ResourcePtr<ResourceCatalog>;
/** Strong, named ownership for Graphics resources. The live registry is never searched here. */
/**
* @brief Thread-safe, strongly owning collection of named graphics resources.
*
* A catalog maps semantic string keys to textures, drawable sources, texture atlases, and fonts.
* Publishing a resource gives the catalog shared ownership of it. Publishing another resource of
* the same kind under the same key replaces that binding; the key and resource name are never
* changed automatically. Publishing a null handle is equivalent to erasing the corresponding key,
* while an empty key is ignored.
*
* Lookups return owning handles. A resource obtained from a catalog therefore remains alive even
* if its binding is subsequently replaced, erased, or the catalog is cleared. Final handles are
* released after dropping the catalog mutex so resource destruction and callbacks never execute
* while the catalog is locked.
*
* Drawable and font hash lookups use String::hash() of the semantic key as a weak secondary index.
* They are compatibility/convenience lookups and do not replace full-key lookup when collision-safe
* identity is required. Textures use ResourceId for process-wide object identity elsewhere; the
* hash accepted by findDrawable() and findFont() is not a ResourceId.
*
* ResourceCatalog performs no parent, scene, live-registry, filesystem, or fallback search. A
* ResourceScope defines lookup precedence by searching its local catalog and then explicitly
* imported catalogs. Importing a catalog shares this object and its live contents; it does not copy
* any resource.
*
* All public operations are safe to call concurrently. Enumeration methods return snapshots and
* allocate vectors containing owning handles.
*/
class EE_API ResourceCatalog {
public:
/** @return A new empty catalog using eepp resource allocation and deletion. */
static ResourceCatalogPtr New();
/** @brief Publishes or replaces a texture binding. A null texture erases @p key. */
void publish( ResourceKey key, TexturePtr texture );
/** @copydoc publish(ResourceKey,TexturePtr) */
void publish( std::string key, TexturePtr texture );
/** @brief Publishes or replaces a drawable-source binding. A null drawable erases @p key. */
void publishDrawable( ResourceKey key, DrawablePtr drawable );
/** @copydoc publishDrawable(ResourceKey,DrawablePtr) */
void publishDrawable( std::string key, DrawablePtr drawable );
/** @brief Publishes or replaces a texture-atlas binding. A null atlas erases @p key. */
void publishAtlas( ResourceKey key, TextureAtlasPtr atlas );
/** @copydoc publishAtlas(ResourceKey,TextureAtlasPtr) */
void publishAtlas( std::string key, TextureAtlasPtr atlas );
/** @brief Publishes or replaces a font binding. A null font erases @p key. */
void publishFont( ResourceKey key, FontPtr font );
/** @copydoc publishFont(ResourceKey,FontPtr) */
void publishFont( std::string key, FontPtr font );
/** @return The texture bound to @p key, or an empty handle when it is not present. */
TexturePtr findTexture( const ResourceKey& key ) const;
/** @copydoc findTexture(const ResourceKey&)const */
TexturePtr findTexture( const std::string& key ) const;
/** @return The drawable source bound to @p key, or an empty handle when it is not present. */
DrawablePtr findDrawable( const ResourceKey& key ) const;
/** @copydoc findDrawable(const ResourceKey&)const */
DrawablePtr findDrawable( const std::string& key ) const;
/**
* @brief Looks up a drawable through the weak String::hash(key) secondary index.
* @return An owning handle when the indexed drawable is still present, otherwise an empty
* handle.
*/
DrawablePtr findDrawable( const String::HashType& id ) const;
/** @return The texture atlas bound to @p key, or an empty handle when it is not present. */
TextureAtlasPtr findAtlas( const ResourceKey& key ) const;
/** @copydoc findAtlas(const ResourceKey&)const */
TextureAtlasPtr findAtlas( const std::string& key ) const;
/** @return An owning snapshot of all texture atlases currently published in this catalog. */
std::vector<TextureAtlasPtr> getAtlases() const;
/** @return The font bound to @p key, or an empty handle when it is not present. */
FontPtr findFont( const ResourceKey& key ) const;
/** @copydoc findFont(const ResourceKey&)const */
FontPtr findFont( const std::string& key ) const;
/**
* @brief Looks up a font through the weak String::hash(key) secondary index.
* @return An owning handle when the indexed font is still present, otherwise an empty handle.
*/
FontPtr findFont( const String::HashType& id ) const;
/** @return An owning snapshot of all fonts currently published in this catalog. */
std::vector<FontPtr> getFonts() const;
/** @brief Removes the texture binding for @p key. @return Whether a binding was removed. */
bool erase( const ResourceKey& key );
/** @copydoc erase(const ResourceKey&) */
bool erase( const std::string& key );
/** @brief Removes the drawable binding for @p key. @return Whether a binding was removed. */
bool eraseDrawable( const ResourceKey& key );
/** @copydoc eraseDrawable(const ResourceKey&) */
bool eraseDrawable( const std::string& key );
/** @brief Removes the texture-atlas binding for @p key. @return Whether a binding was removed.
*/
bool eraseAtlas( const ResourceKey& key );
/** @copydoc eraseAtlas(const ResourceKey&) */
bool eraseAtlas( const std::string& key );
/** @brief Removes the font binding for @p key. @return Whether a binding was removed. */
bool eraseFont( const ResourceKey& key );
/** @copydoc eraseFont(const ResourceKey&) */
bool eraseFont( const std::string& key );
/**
* @brief Removes @p font only when its current name maps to that exact font in this catalog.
* @return Whether the matching binding was removed.
*/
bool eraseFont( Font* font );
/** @brief Removes every binding while allowing previously returned handles to remain valid. */
void clear();
/** @return The total number of texture, drawable, atlas, and font bindings. */
std::size_t size() const;
private:
@@ -49,6 +139,8 @@ class EE_API ResourceCatalog {
UnorderedMap<std::string, DrawablePtr> mDrawables;
UnorderedMap<String::HashType, DrawableWeakPtr> mDrawablesById;
UnorderedMap<std::string, TextureAtlasPtr> mAtlases;
UnorderedMap<std::string, FontPtr> mFonts;
UnorderedMap<String::HashType, FontWeakPtr> mFontsById;
};
}} // namespace EE::Graphics
+50 -2
View File
@@ -2,6 +2,7 @@
#define EE_GRAPHICS_RESOURCESCOPE_HPP
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/resourcecatalog.hpp>
#include <eepp/graphics/textureregion.hpp>
@@ -10,12 +11,30 @@ namespace EE { namespace Graphics {
class ResourceScope;
using ResourceScopePtr = ResourcePtr<ResourceScope>;
/** Graphics-only semantic lookup boundary with a local catalog and explicit catalog imports. */
/**
* @brief Graphics resource lookup boundary with local ownership and explicit catalog visibility.
*
* A scope owns resources published into its local catalog. Lookups search that local catalog first,
* followed by imported catalogs in import order. Importing a catalog retains the catalog and makes
* its resources visible; it does not copy resources and does not transfer them into the local
* catalog. Consequently, removing an import only removes lookup visibility and releases the
* scope's catalog reference.
*
* Use importCatalog() when resources owned by another lifetime boundary must be visible in this
* scope, such as application assets shared with a scene or a theme catalog used by UI widgets.
* Avoid importing unrelated scene or document catalogs: keeping imports explicit prevents name
* collisions and resource leakage between independent documents. UISceneNode imports the default
* resource catalog automatically unless that behavior is disabled at construction time.
*/
class EE_API ResourceScope {
public:
static ResourceScopePtr New();
ResourceScope();
~ResourceScope();
FontService& getFontService();
const FontService& getFontService() const;
TexturePtr findTexture( const ResourceKey& key ) const;
TexturePtr findTexture( const std::string& key ) const;
@@ -26,6 +45,10 @@ class EE_API ResourceScope {
TextureAtlasPtr findAtlas( const ResourceKey& key ) const;
TextureAtlasPtr findAtlas( const std::string& key ) const;
std::vector<TextureAtlasPtr> getAtlases() const;
FontPtr findFont( const ResourceKey& key ) const;
FontPtr findFont( const std::string& key ) const;
FontPtr findFont( const String::HashType& id ) const;
std::vector<FontPtr> getFonts() const;
std::vector<TextureRegionPtr>
findTextureRegionsByPattern( const std::string& name, const std::string& extension = "",
TextureAtlas* searchInTextureAtlas = nullptr ) const;
@@ -39,27 +62,52 @@ class EE_API ResourceScope {
void publishLocalDrawable( std::string key, DrawablePtr drawable );
void publishLocalAtlas( ResourceKey key, TextureAtlasPtr atlas );
void publishLocalAtlas( std::string key, TextureAtlasPtr atlas );
/**
* @brief Publishes a font under @p key, replacing any existing local binding for that key.
*
* The requested semantic key is preserved. Fonts are never renamed to avoid a collision.
*/
void publishLocalFont( ResourceKey key, FontPtr font );
void publishLocalFont( std::string key, FontPtr font );
bool eraseLocal( const ResourceKey& key );
bool eraseLocal( const std::string& key );
bool eraseLocalDrawable( const ResourceKey& key );
bool eraseLocalDrawable( const std::string& key );
bool eraseLocalAtlas( const ResourceKey& key );
bool eraseLocalAtlas( const std::string& key );
bool eraseLocalFont( const ResourceKey& key );
bool eraseLocalFont( const std::string& key );
bool eraseLocalFont( Font* font );
void clearLocal();
/**
* @brief Makes resources from @p catalog visible after this scope's local resources.
*
* Importing the same catalog more than once has no effect. The catalog is retained strongly for
* as long as it remains imported. Catalog contents stay live: resources published after this
* call become visible without importing the catalog again.
*/
void importCatalog( ResourceCatalogPtr catalog );
/** @brief Removes an imported catalog without modifying the catalog or its resources. */
bool removeCatalog( const ResourceCatalogPtr& catalog );
/** @brief Removes every imported catalog while preserving this scope's local resources. */
void clearImports();
ResourceCatalogPtr getLocalCatalog() const;
private:
void attachFontService( const FontPtr& font );
void detachFontService( const FontPtr& font );
ResourceCatalogPtr mLocalCatalog;
FontService mFontService;
std::vector<ResourceCatalogPtr> mImports;
mutable System::Mutex mMutex;
};
/** Engine-owned process defaults for pure Graphics and legacy application-wide resolution. */
/** Engine-owned process defaults for pure Graphics and application-wide resolution. */
EE_API ResourceCatalog& globalResourceCatalog();
EE_API ResourceScope& defaultResourceScope();
+10 -1
View File
@@ -48,7 +48,16 @@ class EE_API TextLayout {
LineWrapMode lineWrapMode = LineWrapMode::NoWrap, Uint32 wrapWidth = 0,
bool keepIndentation = false, Float initialXOffset = 0 );
static void clearLayoutCache();
/**
* Removes entries from the shared text-layout LRU cache.
*
* @param font Optional borrowed font identity. When provided, only layouts requested with this
* font or containing shaped glyphs produced by this font are evicted. Passing nullptr clears
* the entire cache. Font destruction uses selective eviction before its borrowed pointers
* become invalid.
*/
static void clearLayoutCache( Font* font = nullptr );
protected:
static void wrapLayout( const String::View& string, TextLayout&, LineWrapMode lineWrapMode,
Float wrapWidth, Float vspace, bool keepIndentation, Font* font,
+6 -1
View File
@@ -118,6 +118,9 @@ class EE_API UIFontPickerDialog : public UIWindow {
std::vector<Uint32> mSizes;
UnorderedSet<std::string> mLoadedFontKeys;
UnorderedMap<std::string, std::string> mFontTags;
Graphics::FontTrueTypePtr mPreviewFont;
Graphics::Font* mPreviewTextDefaultFont{ nullptr };
Graphics::Font* mPreviewInputDefaultFont{ nullptr };
std::shared_ptr<Models::Model> mFamilyModel;
std::shared_ptr<Models::Model> mStyleModel;
std::shared_ptr<Models::Model> mSizeModel;
@@ -171,7 +174,7 @@ class EE_API UIFontPickerDialog : public UIWindow {
void sortFonts();
void mergeFontManagerFonts( std::vector<FontDesc>& fonts );
void mergeLoadedFonts( std::vector<FontDesc>& fonts );
void updateFontTags();
@@ -189,6 +192,8 @@ class EE_API UIFontPickerDialog : public UIWindow {
void updatePreview();
void clearPreviewFont();
void selectInitialRows();
void selectFamily( const std::string& family );
+17 -4
View File
@@ -23,6 +23,7 @@ using namespace EE::Network;
namespace EE { namespace Graphics {
class Font;
using FontPtr = ResourcePtr<Font>;
}} // namespace EE::Graphics
namespace EE { namespace Window {
@@ -57,9 +58,14 @@ class EE_API UISceneNode : public SceneNode {
*
* @param window Pointer to the window to associate with this UI scene node.
* If NULL, uses the current window from Engine.
* @param importDefaultResources Whether the scene scope automatically imports the catalog from
* Graphics::defaultResourceScope(). Keep this enabled for normal
* application scenes. Disable it for intentionally isolated
* scenes that must only resolve local or explicitly imported resources.
* @return Pointer to the newly created UISceneNode instance.
*/
static UISceneNode* New( EE::Window::Window* window = NULL );
static UISceneNode* New( EE::Window::Window* window = NULL,
bool importDefaultResources = true );
/**
* @brief Destroys the UISceneNode and cleans up resources.
@@ -782,7 +788,12 @@ class EE_API UISceneNode : public SceneNode {
/** @return The Graphics resource lookup and ownership boundary of this scene. */
const Graphics::ResourceScopePtr& getResourceScope() const;
/** Replaces this scene's resource boundary, allowing intentional sharing between scenes. */
/**
* @brief Replaces this scene's resource boundary, allowing intentional sharing between scenes.
*
* Scenes created with default-resource importing enabled also import the default catalog into
* the replacement scope. Scenes created with it disabled leave the replacement scope unchanged.
*/
UISceneNode* setResourceScope( Graphics::ResourceScopePtr resourceScope );
/**
@@ -928,10 +939,11 @@ class EE_API UISceneNode : public SceneNode {
bool mStyleDuringLoad{ false };
UIThemeManager* mUIThemeManager{ nullptr };
UIIconThemeManager* mUIIconThemeManager{ nullptr };
std::vector<Font*> mFontFaces;
std::vector<Graphics::FontPtr> mFontFaces;
UnorderedMap<std::string, Font*> mFontFaceAliases;
UnorderedMap<Font*, std::string> mFontFaceFamilies;
std::shared_ptr<AsyncResourceLoadState> mAsyncResourceLoadState;
bool mImportDefaultResources{ true };
Graphics::ResourceScopePtr mResourceScope;
DrawableResolver mDrawableResolver;
WebResourceCachePtr mWebResourceCache;
@@ -971,8 +983,9 @@ class EE_API UISceneNode : public SceneNode {
* Creates a UISceneNode with optional window association.
*
* @param window Pointer to the window, or NULL for default.
* @param importDefaultResources Whether the scene scope imports the default resource catalog.
*/
explicit UISceneNode( EE::Window::Window* window = NULL );
explicit UISceneNode( EE::Window::Window* window = NULL, bool importDefaultResources = true );
/**
* @brief Handles node resize.
+2 -2
View File
@@ -62,7 +62,7 @@
../../include/eepp/graphics/fontbmfont.hpp
../../include/eepp/graphics/font.hpp
../../include/eepp/graphics/fontfamily.hpp
../../include/eepp/graphics/fontmanager.hpp
../../include/eepp/graphics/fontservice.hpp
../../include/eepp/graphics/fontsprite.hpp
../../include/eepp/graphics/fontstyleconfig.hpp
../../include/eepp/graphics/fonttruetype.hpp
@@ -560,7 +560,7 @@
../../src/eepp/graphics/fontbmfont.cpp
../../src/eepp/graphics/font.cpp
../../src/eepp/graphics/fontfamily.cpp
../../src/eepp/graphics/fontmanager.cpp
../../src/eepp/graphics/fontservice.cpp
../../src/eepp/graphics/fontsprite.cpp
../../src/eepp/graphics/fonttruetype.cpp
../../src/eepp/graphics/framebuffer.cpp
+2 -2
View File
@@ -62,7 +62,7 @@
../../include/eepp/graphics/fontbmfont.hpp
../../include/eepp/graphics/font.hpp
../../include/eepp/graphics/fontfamily.hpp
../../include/eepp/graphics/fontmanager.hpp
../../include/eepp/graphics/fontservice.hpp
../../include/eepp/graphics/fontsprite.hpp
../../include/eepp/graphics/fontstyleconfig.hpp
../../include/eepp/graphics/fonttruetype.hpp
@@ -551,7 +551,7 @@
../../src/eepp/graphics/fontbmfont.cpp
../../src/eepp/graphics/font.cpp
../../src/eepp/graphics/fontfamily.cpp
../../src/eepp/graphics/fontmanager.cpp
../../src/eepp/graphics/fontservice.cpp
../../src/eepp/graphics/fontsprite.cpp
../../src/eepp/graphics/fonttruetype.cpp
../../src/eepp/graphics/framebuffer.cpp
+2 -2
View File
@@ -60,7 +60,7 @@
../../include/eepp/ui/webresourcecache.hpp
../../include/eepp/graphics/fontbmfont.hpp
../../include/eepp/graphics/font.hpp
../../include/eepp/graphics/fontmanager.hpp
../../include/eepp/graphics/fontservice.hpp
../../include/eepp/graphics/fontsprite.hpp
../../include/eepp/graphics/fontstyleconfig.hpp
../../include/eepp/graphics/fonttruetype.hpp
@@ -542,7 +542,7 @@
../../src/eepp/ui/webresourcecache.cpp
../../src/eepp/graphics/fontbmfont.cpp
../../src/eepp/graphics/font.cpp
../../src/eepp/graphics/fontmanager.cpp
../../src/eepp/graphics/fontservice.cpp
../../src/eepp/graphics/fontsprite.cpp
../../src/eepp/graphics/fonttruetype.cpp
../../src/eepp/graphics/framebuffer.cpp
+3 -3
View File
@@ -236,7 +236,7 @@ UTEST( Benchmark, InlineLayout ) {
800, 600, "bench", WindowStyle::Default, WindowBackend::Default, 32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
if ( !font->loaded() ) {
Engine::destroySingleton();
@@ -323,9 +323,9 @@ UTEST( Benchmark, MarkdownReadme ) {
UISceneNode* ui = UISceneNode::New( window );
SceneManager::instance()->add( ui );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontTrueType* monoFont = FontTrueType::New( "monospace" );
FontTrueType* monoFont = FontTrueType::New( "monospace" ).get();
monoFont->loadFromFile( "../assets/fonts/DejaVuSansMono.ttf" );
if ( !font->loaded() || !monoFont->loaded() ) {
Engine::destroySingleton();
+6 -7
View File
@@ -1,5 +1,4 @@
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/window/engine.hpp>
@@ -80,19 +79,19 @@ std::vector<std::size_t> Font::emojiCodePointsPositions( const String& string )
Font::Font( const FontType& Type, const std::string& Name ) : mType( Type ), mNumCallBacks( 0 ) {
this->setName( Name );
FontManager::instance()->add( this );
}
Font::~Font() {
if ( !FontManager::instance()->isDestroying() ) {
FontManager::instance()->remove( this, false );
}
}
Font::~Font() {}
const FontType& Font::getType() const {
return mType;
}
Float Font::getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness ) const {
return getGlyph( codePoint, characterSize, bold, italic, outlineThickness ).advance;
}
const std::string& Font::getName() const {
return mFontName;
}
+25 -4
View File
@@ -1,4 +1,5 @@
#include <eepp/graphics/fontbmfont.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/iostream.hpp>
@@ -10,12 +11,27 @@
namespace EE { namespace Graphics {
FontBMFont* FontBMFont::New( const std::string fontName ) {
return eeNew( FontBMFont, ( fontName ) );
FontBMFontPtr FontBMFont::New( const std::string fontName ) {
FontBMFontPtr font( eeNew( FontBMFont, ( fontName ) ), ResourceDeleter<FontBMFont>() );
defaultResourceScope().publishLocalFont( fontName, font );
return font;
}
FontBMFont* FontBMFont::New( const std::string fontName, const std::string& filename ) {
FontBMFont* fontBMFont = New( fontName );
FontBMFontPtr FontBMFont::New( const std::string fontName, ResourceScope& resourceScope ) {
FontBMFontPtr font( eeNew( FontBMFont, ( fontName ) ), ResourceDeleter<FontBMFont>() );
resourceScope.publishLocalFont( fontName, font );
return font;
}
FontBMFontPtr FontBMFont::New( const std::string fontName, const std::string& filename ) {
FontBMFontPtr fontBMFont = New( fontName );
fontBMFont->loadFromFile( filename );
return fontBMFont;
}
FontBMFontPtr FontBMFont::New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope ) {
FontBMFontPtr fontBMFont = New( fontName, resourceScope );
fontBMFont->loadFromFile( filename );
return fontBMFont;
}
@@ -194,6 +210,11 @@ Glyph FontBMFont::getGlyph( Uint32 codePoint, unsigned int characterSize, bool b
}
}
Float FontBMFont::getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold,
bool italic, Float outlineThickness ) const {
return getGlyph( codePoint, characterSize, bold, italic, outlineThickness ).advance;
}
GlyphDrawable* FontBMFont::getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
bool bold, bool italic,
Float outlineThickness ) const {
+9 -5
View File
@@ -1,4 +1,5 @@
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/system/filesystem.hpp>
using namespace std::literals;
@@ -53,11 +54,15 @@ std::string FontFamily::findType( const std::string& fontpath, const std::string
return "";
}
FontTrueType* FontFamily::setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType ) {
void FontFamily::setFont( FontTrueType* font, const std::string& fontpath,
const std::string_view& fontType ) {
if ( fontpath.empty() )
return nullptr;
FontTrueType* loadedFont = FontTrueType::New( font->getName() + "-" + fontType, fontpath );
return;
FontService* fontService = font->getFontService();
FontTrueTypePtr loadedFont =
fontService ? FontTrueType::New( font->getName() + "-" + fontType, fontpath,
fontService->getResourceScope() )
: FontTrueType::New( font->getName() + "-" + fontType, fontpath );
if ( fontType == "bold"sv )
font->setBoldFont( loadedFont );
else if ( fontType == "italic"sv )
@@ -66,7 +71,6 @@ FontTrueType* FontFamily::setFont( FontTrueType* font, const std::string& fontpa
font->setBoldItalicFont( loadedFont );
loadedFont->setBoldAdvanceSameAsRegular( font->getBoldAdvanceSameAsRegular() );
loadedFont->setEnableDynamicMonospace( font->getEnableDynamicMonospace() );
return loadedFont;
}
}} // namespace EE::Graphics
-131
View File
@@ -1,131 +0,0 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/system/filesystem.hpp>
namespace EE { namespace Graphics {
SINGLETON_DECLARE_IMPLEMENTATION( FontManager )
FontManager::FontManager() {}
FontManager::~FontManager() {
mEmojiFont = nullptr;
mColorEmojiFont = nullptr;
mFallbackFonts.clear();
mSystemFallbackFonts.clear();
}
Graphics::Font* FontManager::add( Graphics::Font* font ) {
eeASSERT( NULL != font );
return ResourceManager<Graphics::Font>::add( font );
}
void FontManager::setColorEmojiFont( Font* font ) {
mColorEmojiFont = font;
}
Graphics::Font* FontManager::getColorEmojiFont() const {
return mColorEmojiFont;
}
Graphics::Font* FontManager::getEmojiFont() const {
return mEmojiFont;
}
void FontManager::setEmojiFont( Graphics::Font* newEmojiFont ) {
mEmojiFont = newEmojiFont;
}
const std::vector<Font*>& FontManager::getFallbackFonts() const {
return mFallbackFonts;
}
bool FontManager::hasFallbackFonts() const {
return !mFallbackFonts.empty();
}
bool FontManager::addFallbackFont( Font* fallbackFont ) {
if ( fallbackFont && std::find( mFallbackFonts.begin(), mFallbackFonts.end(), fallbackFont ) ==
mFallbackFonts.end() ) {
mFallbackFonts.emplace_back( fallbackFont );
return true;
}
return false;
}
bool FontManager::removeFallbackFont( Font* fallbackFont ) {
auto fallbackFontIt = std::find( mFallbackFonts.begin(), mFallbackFonts.end(), fallbackFont );
if ( fallbackFontIt != mFallbackFonts.end() ) {
mFallbackFonts.erase( fallbackFontIt );
return true;
}
return false;
}
FontHinting FontManager::getHinting() const {
return mHinting;
}
void FontManager::setHinting( FontHinting hinting ) {
mHinting = hinting;
for ( auto [_, font] : mResources ) {
if ( font->getType() == FontType::TTF ) {
auto ttf = static_cast<FontTrueType*>( font );
if ( !ttf->isEmojiFont() )
ttf->setHinting( hinting );
}
}
}
FontAntialiasing FontManager::getAntialiasing() const {
return mAntialiasing;
}
void FontManager::setAntialiasing( FontAntialiasing antialiasing ) {
mAntialiasing = antialiasing;
for ( auto [_, font] : mResources ) {
if ( font->getType() == FontType::TTF ) {
auto ttf = static_cast<FontTrueType*>( font );
if ( !ttf->isEmojiFont() )
ttf->setAntialiasing( antialiasing );
}
}
}
Font* FontManager::getByInternalId( Uint32 internalId ) const {
for ( auto [_, font] : mResources ) {
if ( font->getType() == FontType::TTF &&
static_cast<FontTrueType*>( font )->getFontInternalId() == internalId )
return font;
}
return nullptr;
}
FontTrueType* FontManager::getOrLoadSystemFallbackFont( const FontDesc& desc ) {
if ( desc.path.empty() )
return nullptr;
for ( auto* font : mSystemFallbackFonts ) {
if ( font->getType() == FontType::TTF ) {
auto* ttf = static_cast<FontTrueType*>( font );
if ( ttf->getInfo().fontpath + ttf->getInfo().filename == desc.path &&
ttf->getFaceIndex() == desc.faceIndex )
return ttf;
}
}
FontTrueType* ttf = FontTrueType::New( desc.family, desc.path, desc.faceIndex );
if ( !ttf || !ttf->loaded() ) {
eeSAFE_DELETE( ttf );
return nullptr;
}
mSystemFallbackFonts.push_back( ttf );
return ttf;
}
}} // namespace EE::Graphics
+162
View File
@@ -0,0 +1,162 @@
#include <algorithm>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
namespace EE { namespace Graphics {
FontService::FontService( ResourceScope& resourceScope ) : mResourceScope( resourceScope ) {}
ResourceScope& FontService::getResourceScope() const {
return mResourceScope;
}
FontPtr FontService::findHandle( Font* font ) const {
if ( !font )
return {};
FontPtr handle = mResourceScope.findFont( font->getId() );
return handle.get() == font ? handle : FontPtr{};
}
void FontService::onFontRemoved( Font* font ) {
if ( mColorEmojiFont.get() == font )
mColorEmojiFont.reset();
if ( mEmojiFont.get() == font )
mEmojiFont.reset();
removeFallbackFont( font );
mSystemFallbackFonts.erase(
std::remove_if( mSystemFallbackFonts.begin(), mSystemFallbackFonts.end(),
[font]( const FontPtr& systemFont ) { return systemFont.get() == font; } ),
mSystemFallbackFonts.end() );
}
void FontService::setColorEmojiFont( Font* font ) {
mColorEmojiFont = findHandle( font );
}
Font* FontService::getColorEmojiFont() const {
return mColorEmojiFont.get();
}
Font* FontService::getEmojiFont() const {
return mEmojiFont.get();
}
void FontService::setEmojiFont( Font* font ) {
mEmojiFont = findHandle( font );
}
const std::vector<FontPtr>& FontService::getFallbackFonts() const {
return mFallbackFonts;
}
bool FontService::hasFallbackFonts() const {
return !mFallbackFonts.empty();
}
bool FontService::addFallbackFont( FontPtr fallbackFont ) {
if ( fallbackFont && std::find( mFallbackFonts.begin(), mFallbackFonts.end(), fallbackFont ) ==
mFallbackFonts.end() ) {
mFallbackFonts.emplace_back( std::move( fallbackFont ) );
return true;
}
return false;
}
bool FontService::addFallbackFont( Font* fallbackFont ) {
return addFallbackFont( findHandle( fallbackFont ) );
}
bool FontService::removeFallbackFont( Font* fallbackFont ) {
auto it = std::find_if(
mFallbackFonts.begin(), mFallbackFonts.end(),
[fallbackFont]( const FontPtr& font ) { return font.get() == fallbackFont; } );
if ( it == mFallbackFonts.end() )
return false;
mFallbackFonts.erase( it );
return true;
}
FontHinting FontService::getHinting() const {
return mHinting;
}
void FontService::setHinting( FontHinting hinting ) {
mHinting = hinting;
for ( const FontPtr& fontHandle : mResourceScope.getFonts() ) {
Font* font = fontHandle.get();
if ( font->getType() == FontType::TTF ) {
auto ttf = static_cast<FontTrueType*>( font );
if ( ttf->getFontService() == this && !ttf->isEmojiFont() )
ttf->setHinting( hinting );
}
}
}
FontAntialiasing FontService::getAntialiasing() const {
return mAntialiasing;
}
void FontService::setAntialiasing( FontAntialiasing antialiasing ) {
mAntialiasing = antialiasing;
for ( const FontPtr& fontHandle : mResourceScope.getFonts() ) {
Font* font = fontHandle.get();
if ( font->getType() == FontType::TTF ) {
auto ttf = static_cast<FontTrueType*>( font );
if ( ttf->getFontService() == this && !ttf->isEmojiFont() )
ttf->setAntialiasing( antialiasing );
}
}
}
Font* FontService::getByInternalId( Uint32 internalId ) const {
for ( const FontPtr& fontHandle : mResourceScope.getFonts() ) {
Font* font = fontHandle.get();
if ( font->getType() == FontType::TTF &&
static_cast<FontTrueType*>( font )->getFontInternalId() == internalId )
return font;
}
return nullptr;
}
ResourcePtr<FontTrueType> FontService::loadSystemFont( const FontDesc& desc ) {
if ( desc.path.empty() )
return {};
FontTrueTypePtr ttf( eeNew( FontTrueType, ( desc.family, *this ) ),
ResourceDeleter<FontTrueType>() );
if ( !ttf->loadFromFile( desc.path, desc.faceIndex ) )
return {};
ttf->setHinting( mHinting );
ttf->setAntialiasing( mAntialiasing );
// A standalone font can outlive this service, so it must not retain a borrowed service pointer.
ttf->setFontService( nullptr );
return ttf;
}
FontTrueType* FontService::getOrLoadSystemFallbackFont( const FontDesc& desc ) {
if ( desc.path.empty() )
return nullptr;
for ( const FontPtr& fontHandle : mSystemFallbackFonts ) {
auto* ttf = static_cast<FontTrueType*>( fontHandle.get() );
if ( ttf->getInfo().fontpath + ttf->getInfo().filename == desc.path &&
ttf->getFaceIndex() == desc.faceIndex )
return ttf;
}
FontTrueTypePtr ttf =
FontTrueType::New( desc.family, desc.path, desc.faceIndex, mResourceScope );
if ( !ttf || !ttf->loaded() ) {
if ( ttf )
mResourceScope.eraseLocalFont( ttf.get() );
return nullptr;
}
mSystemFallbackFonts.emplace_back( ttf );
return ttf.get();
}
}} // namespace EE::Graphics
+20 -4
View File
@@ -1,4 +1,5 @@
#include <eepp/graphics/fontsprite.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/iostream.hpp>
@@ -10,12 +11,27 @@
namespace EE { namespace Graphics {
FontSprite* FontSprite::New( const std::string fontName ) {
return eeNew( FontSprite, ( fontName ) );
FontSpritePtr FontSprite::New( const std::string fontName ) {
FontSpritePtr font( eeNew( FontSprite, ( fontName ) ), ResourceDeleter<FontSprite>() );
defaultResourceScope().publishLocalFont( fontName, font );
return font;
}
FontSprite* FontSprite::New( const std::string fontName, const std::string& filename ) {
FontSprite* fontSprite = New( fontName );
FontSpritePtr FontSprite::New( const std::string fontName, ResourceScope& resourceScope ) {
FontSpritePtr font( eeNew( FontSprite, ( fontName ) ), ResourceDeleter<FontSprite>() );
resourceScope.publishLocalFont( fontName, font );
return font;
}
FontSpritePtr FontSprite::New( const std::string fontName, const std::string& filename ) {
FontSpritePtr fontSprite = New( fontName );
fontSprite->loadFromFile( filename );
return fontSprite;
}
FontSpritePtr FontSprite::New( const std::string fontName, const std::string& filename,
ResourceScope& resourceScope ) {
FontSpritePtr fontSprite = New( fontName, resourceScope );
fontSprite->loadFromFile( filename );
return fontSprite;
}
+200 -139
View File
@@ -1,8 +1,10 @@
#include <eepp/core/retainsymbol.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/graphics/textlayout.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/iostream.hpp>
@@ -266,24 +268,49 @@ static inline Uint64 getKerningKey( Uint32 first, Uint32 second, unsigned int ch
( static_cast<Uint64>( static_cast<Uint32>( outlineThickness * 100.f ) & 0xFF ) );
}
FontTrueType* FontTrueType::New( const std::string& FontName ) {
return eeNew( FontTrueType, ( FontName ) );
FontTrueTypePtr FontTrueType::New( const std::string& FontName ) {
FontTrueTypePtr font(
eeNew( FontTrueType, ( FontName, defaultResourceScope().getFontService() ) ),
ResourceDeleter<FontTrueType>() );
defaultResourceScope().publishLocalFont( FontName, font );
return font;
}
FontTrueType* FontTrueType::New( const std::string& FontName, const std::string& filename ) {
FontTrueType* fontTrueType = New( FontName );
FontTrueTypePtr FontTrueType::New( const std::string& FontName, ResourceScope& resourceScope ) {
FontTrueTypePtr font( eeNew( FontTrueType, ( FontName, resourceScope.getFontService() ) ),
ResourceDeleter<FontTrueType>() );
resourceScope.publishLocalFont( FontName, font );
return font;
}
FontTrueTypePtr FontTrueType::New( const std::string& FontName, const std::string& filename ) {
FontTrueTypePtr fontTrueType = New( FontName );
fontTrueType->loadFromFile( filename );
return fontTrueType;
}
FontTrueType* FontTrueType::New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex ) {
FontTrueType* fontTrueType = New( FontName );
FontTrueTypePtr FontTrueType::New( const std::string& FontName, const std::string& filename,
ResourceScope& resourceScope ) {
FontTrueTypePtr fontTrueType = New( FontName, resourceScope );
fontTrueType->loadFromFile( filename );
return fontTrueType;
}
FontTrueTypePtr FontTrueType::New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex ) {
FontTrueTypePtr fontTrueType = New( FontName );
fontTrueType->loadFromFile( filename, faceIndex );
return fontTrueType;
}
FontTrueType::FontTrueType( const std::string& FontName ) :
FontTrueTypePtr FontTrueType::New( const std::string& FontName, const std::string& filename,
Uint32 faceIndex, ResourceScope& resourceScope ) {
FontTrueTypePtr fontTrueType = New( FontName, resourceScope );
fontTrueType->loadFromFile( filename, faceIndex );
return fontTrueType;
}
FontTrueType::FontTrueType( const std::string& FontName, FontService& fontService ) :
Font( FontType::TTF, FontName ),
mLibrary( NULL ),
mFace( NULL ),
@@ -307,17 +334,19 @@ FontTrueType::FontTrueType( const std::string& FontName ) :
mIsBold( false ),
mIsItalic( false ),
mIsMonospaceCompletePending( false ),
mHinting( FontManager::instance()->getHinting() ),
mAntialiasing( FontManager::instance()->getAntialiasing() ),
mFaceIndex( 0 ),
mFontBold( nullptr ),
mFontItalic( nullptr ),
mFontBoldItalic( nullptr ),
mFontBoldCb( 0 ),
mFontItalicCb( 0 ),
mFontBoldItalicCb( 0 ) {}
mHinting( fontService.getHinting() ),
mAntialiasing( fontService.getAntialiasing() ),
mFontService( &fontService ),
mFaceIndex( 0 ) {}
void FontTrueType::setFontService( FontService* fontService ) {
mFontService = fontService;
}
FontTrueType::~FontTrueType() {
// Cached shaped glyphs borrow FontTrueType pointers. Drop layouts referencing this font before
// it dies, while preserving unrelated entries in the shared cache.
TextLayout::clearLayoutCache( this );
cleanup();
}
@@ -516,12 +545,12 @@ bool FontTrueType::setFontFace( void* _face ) {
#endif
}
if ( ( mIsColorEmojiFont || mHasColrGlyphs ) &&
FontManager::instance()->getColorEmojiFont() == nullptr )
FontManager::instance()->setColorEmojiFont( this );
if ( mFontService && ( mIsColorEmojiFont || mHasColrGlyphs ) &&
mFontService->getColorEmojiFont() == nullptr )
mFontService->setColorEmojiFont( this );
if ( mIsEmojiFont && !mHasSvgGlyphs && FontManager::instance()->getEmojiFont() == nullptr )
FontManager::instance()->setEmojiFont( this );
if ( mFontService && mIsEmojiFont && !mHasSvgGlyphs && mFontService->getEmojiFont() == nullptr )
mFontService->setEmojiFont( this );
// Load the stroker that will be used to outline the font
FT_Stroker stroker = nullptr;
@@ -611,6 +640,7 @@ bool FontTrueType::setVariableFontWeight( FontWeight weight ) {
mKeyCache.clear();
mKerningCache.clear();
mKerningGlyphCache.clear();
mGlyphAdvanceCache.clear();
#ifdef EE_TEXT_SHAPER_ENABLED
if ( mHBFont )
hb_ft_font_changed( static_cast<hb_font_t*>( mHBFont ) );
@@ -649,11 +679,11 @@ Glyph FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool
Uint32 idx = 0;
if ( mEnableEmojiFallback && !mIsColorEmojiFont && !mHasSvgGlyphs && !mHasColrGlyphs &&
!mIsEmojiFont && Font::isEmojiCodePoint( codePoint ) ) {
if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr &&
FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF ) {
if ( mFontService && !mIsColorEmojiFont && mFontService->getColorEmojiFont() != nullptr &&
mFontService->getColorEmojiFont()->getType() == FontType::TTF ) {
FontTrueType* fontEmoji =
static_cast<FontTrueType*>( FontManager::instance()->getColorEmojiFont() );
static_cast<FontTrueType*>( mFontService->getColorEmojiFont() );
if ( ( idx = fontEmoji->getGlyphIndex( codePoint ) ) ) {
if ( mIsMonospace && mEnableDynamicMonospace ) {
mIsMonospaceComplete = false;
@@ -662,11 +692,10 @@ Glyph FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool
return fontEmoji->getGlyphByIndex( idx, characterSize, bold, italic,
outlineThickness, getPage( characterSize ) );
}
} else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr &&
FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) {
} else if ( mFontService && !mIsEmojiFont && mFontService->getEmojiFont() != nullptr &&
mFontService->getEmojiFont()->getType() == FontType::TTF ) {
FontTrueType* fontEmoji =
static_cast<FontTrueType*>( FontManager::instance()->getEmojiFont() );
FontTrueType* fontEmoji = static_cast<FontTrueType*>( mFontService->getEmojiFont() );
if ( ( idx = fontEmoji->getGlyphIndex( codePoint ) ) ) {
if ( mIsMonospace && mEnableDynamicMonospace ) {
mIsMonospaceComplete = false;
@@ -678,27 +707,26 @@ Glyph FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool
}
}
if ( bold && italic && mFontBoldItalic != nullptr &&
if ( bold && italic && mFontBoldItalic &&
( idx = mFontBoldItalic->getGlyphIndex( codePoint ) ) ) {
return mFontBoldItalic->getGlyphByIndex( idx, characterSize, true, true, outlineThickness,
getPage( characterSize ) );
}
if ( bold && !italic && mFontBold != nullptr &&
( idx = mFontBold->getGlyphIndex( codePoint ) ) ) {
if ( bold && !italic && mFontBold && ( idx = mFontBold->getGlyphIndex( codePoint ) ) ) {
return mFontBold->getGlyphByIndex( idx, characterSize, true, false, outlineThickness,
getPage( characterSize ) );
}
if ( italic && !bold && mFontItalic != nullptr &&
( idx = mFontItalic->getGlyphIndex( codePoint ) ) ) {
if ( italic && !bold && mFontItalic && ( idx = mFontItalic->getGlyphIndex( codePoint ) ) ) {
return mFontItalic->getGlyphByIndex( idx, characterSize, false, true, outlineThickness,
getPage( characterSize ) );
}
idx = getGlyphIndex( codePoint );
if ( 0 == idx && mEnableFallbackFont && FontManager::instance()->hasFallbackFonts() ) {
for ( Font* fallbackFontPtr : FontManager::instance()->getFallbackFonts() ) {
if ( 0 == idx && mEnableFallbackFont && mFontService && mFontService->hasFallbackFonts() ) {
for ( const FontPtr& fallbackFontHandle : mFontService->getFallbackFonts() ) {
Font* fallbackFontPtr = fallbackFontHandle.get();
if ( fallbackFontPtr->getType() != FontType::TTF )
continue;
FontTrueType* fallbackFont = static_cast<FontTrueType*>( fallbackFontPtr );
@@ -718,7 +746,7 @@ Glyph FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool
codePoint, FontWeight::Normal, false );
if ( !fallbackDesc.path.empty() ) {
FontTrueType* systemFallback =
FontManager::instance()->getOrLoadSystemFallbackFont( fallbackDesc );
mFontService ? mFontService->getOrLoadSystemFallbackFont( fallbackDesc ) : nullptr;
if ( systemFallback && ( idx = systemFallback->getGlyphIndex( codePoint ) ) ) {
if ( mIsMonospace && mEnableDynamicMonospace ) {
mIsMonospaceComplete = false;
@@ -791,10 +819,11 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
if ( mEnableEmojiFallback && Font::isEmojiCodePoint( codePoint ) && !mIsColorEmojiFont &&
!mIsEmojiFont ) {
if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr &&
FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF ) {
if ( mFontService && !mIsColorEmojiFont &&
mFontService->getColorEmojiFont() != nullptr &&
mFontService->getColorEmojiFont()->getType() == FontType::TTF ) {
FontTrueType* fontEmoji =
static_cast<FontTrueType*>( FontManager::instance()->getColorEmojiFont() );
static_cast<FontTrueType*>( mFontService->getColorEmojiFont() );
tGlyphIndex = fontEmoji->getGlyphIndex( codePoint );
if ( 0 != tGlyphIndex ) {
glyphIndex = tGlyphIndex;
@@ -802,10 +831,10 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
} else {
glyphIndex = getGlyphIndex( codePoint );
}
} else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr &&
FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) {
} else if ( mFontService && !mIsEmojiFont && mFontService->getEmojiFont() != nullptr &&
mFontService->getEmojiFont()->getType() == FontType::TTF ) {
FontTrueType* fontEmoji =
static_cast<FontTrueType*>( FontManager::instance()->getEmojiFont() );
static_cast<FontTrueType*>( mFontService->getEmojiFont() );
tGlyphIndex = fontEmoji->getGlyphIndex( codePoint );
if ( 0 != tGlyphIndex ) {
glyphIndex = tGlyphIndex;
@@ -820,29 +849,30 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
glyphIndex = getGlyphIndex( codePoint );
}
if ( bold && italic && mFontBoldItalic != nullptr &&
if ( bold && italic && mFontBoldItalic &&
( tGlyphIndex = mFontBoldItalic->getGlyphIndex( codePoint ) ) ) {
glyphIndex = tGlyphIndex;
fontInternalId = mFontBoldItalic->getFontInternalId();
isItalic = true;
}
if ( bold && !italic && mFontBold != nullptr &&
if ( bold && !italic && mFontBold &&
( tGlyphIndex = mFontBold->getGlyphIndex( codePoint ) ) ) {
glyphIndex = tGlyphIndex;
fontInternalId = mFontBold->getFontInternalId();
}
if ( italic && !bold && mFontItalic != nullptr &&
if ( italic && !bold && mFontItalic &&
( tGlyphIndex = mFontItalic->getGlyphIndex( codePoint ) ) ) {
glyphIndex = tGlyphIndex;
fontInternalId = mFontItalic->getFontInternalId();
isItalic = true;
}
if ( 0 == glyphIndex && mEnableFallbackFont &&
FontManager::instance()->hasFallbackFonts() ) {
for ( Font* fontFallbackPtr : FontManager::instance()->getFallbackFonts() ) {
if ( 0 == glyphIndex && mEnableFallbackFont && mFontService &&
mFontService->hasFallbackFonts() ) {
for ( const FontPtr& fontFallbackHandle : mFontService->getFallbackFonts() ) {
Font* fontFallbackPtr = fontFallbackHandle.get();
if ( fontFallbackPtr->getType() != FontType::TTF )
continue;
FontTrueType* fontFallback = static_cast<FontTrueType*>( fontFallbackPtr );
@@ -866,7 +896,8 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
codePoint, FontWeight::Normal, false );
if ( !fallbackDesc.path.empty() ) {
FontTrueType* systemFallback =
FontManager::instance()->getOrLoadSystemFallbackFont( fallbackDesc );
mFontService ? mFontService->getOrLoadSystemFallbackFont( fallbackDesc )
: nullptr;
if ( systemFallback &&
( tGlyphIndex = systemFallback->getGlyphIndex( codePoint ) ) ) {
glyphIndex = tGlyphIndex;
@@ -1143,15 +1174,15 @@ bool FontTrueType::loaded() const {
return NULL != mFace;
}
FontService* FontTrueType::getFontService() const {
return mFontService;
}
void FontTrueType::cleanup() {
sendEvent( Event::Unload );
if ( FontManager::existsSingleton() && FontManager::instance()->getColorEmojiFont() == this )
FontManager::instance()->setColorEmojiFont( nullptr );
disconnectBoldItalicFont();
disconnectBoldFont();
disconnectItalicFont();
if ( mFontService && mFontService->getColorEmojiFont() == this )
mFontService->setColorEmojiFont( nullptr );
mCallbacks.clear();
mNumCallBacks = 0;
@@ -1202,16 +1233,14 @@ void FontTrueType::cleanup() {
mIsBold = false;
mIsItalic = false;
mIsMonospaceCompletePending = false;
mFontBold = nullptr;
mFontItalic = nullptr;
mFontBoldItalic = nullptr;
mFontBoldCb = 0;
mFontItalicCb = 0;
mFontBoldItalicCb = 0;
mFontBold.reset();
mFontItalic.reset();
mFontBoldItalic.reset();
mPages.clear();
std::vector<Uint8>().swap( mPixelBuffer );
mKerningCache.clear();
mKerningGlyphCache.clear();
mGlyphAdvanceCache.clear();
mCodePointIndexCache.clear();
mKeyCache.clear();
mClosestCharacterSize.clear();
@@ -1226,6 +1255,81 @@ static int fontSetLoadOptions( FontAntialiasing antialiasing, FontHinting hintin
return load_target | hint;
}
Float FontTrueType::getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold,
bool italic, Float outlineThickness ) const {
Uint32 index = 0;
if ( mEnableEmojiFallback && !mIsColorEmojiFont && !mHasSvgGlyphs && !mHasColrGlyphs &&
!mIsEmojiFont && mFontService && Font::isEmojiCodePoint( codePoint ) ) {
Font* emojiFont = mFontService->getColorEmojiFont();
if ( !emojiFont )
emojiFont = mFontService->getEmojiFont();
if ( emojiFont && emojiFont->getType() == FontType::TTF ) {
auto emojiTrueType = static_cast<FontTrueType*>( emojiFont );
if ( emojiTrueType->getGlyphIndex( codePoint ) )
return emojiTrueType->getGlyphAdvance( codePoint, characterSize, bold, italic,
outlineThickness );
}
}
if ( bold && italic ) {
if ( mFontBoldItalic && ( index = mFontBoldItalic->getGlyphIndex( codePoint ) ) )
return mFontBoldItalic->getGlyphAdvance( codePoint, characterSize, true, true,
outlineThickness );
} else if ( bold ) {
if ( mFontBold && ( index = mFontBold->getGlyphIndex( codePoint ) ) )
return mFontBold->getGlyphAdvance( codePoint, characterSize, true, false,
outlineThickness );
} else if ( italic ) {
if ( mFontItalic && ( index = mFontItalic->getGlyphIndex( codePoint ) ) )
return mFontItalic->getGlyphAdvance( codePoint, characterSize, false, true,
outlineThickness );
}
const FontTrueType* advanceFont = this;
index = getGlyphIndex( codePoint );
if ( index == 0 && mEnableFallbackFont && mFontService && mFontService->hasFallbackFonts() ) {
for ( const FontPtr& fallbackHandle : mFontService->getFallbackFonts() ) {
if ( !fallbackHandle || fallbackHandle->getType() != FontType::TTF )
continue;
auto fallbackFont = static_cast<FontTrueType*>( fallbackHandle.get() );
if ( ( index = fallbackFont->getGlyphIndex( codePoint ) ) ) {
advanceFont = fallbackFont;
break;
}
}
}
if ( index == 0 && mEnableSystemFallback && mFontService &&
SystemFontResolver::existsSingleton() ) {
FontDesc fallbackDesc = SystemFontResolver::instance()->getFallbackForCodepoint(
codePoint, FontWeight::Normal, false );
FontTrueType* fallbackFont =
fallbackDesc.path.empty() ? nullptr
: mFontService->getOrLoadSystemFallbackFont( fallbackDesc );
if ( fallbackFont && ( index = fallbackFont->getGlyphIndex( codePoint ) ) )
advanceFont = fallbackFont;
}
Uint64 key = getIndexKey( advanceFont->mFontInternalId, index, bold, italic, outlineThickness );
auto& advances = advanceFont->mGlyphAdvanceCache[characterSize];
auto advanceIt = advances.find( key );
if ( advanceIt != advances.end() )
return advanceIt->second;
FT_Face face = static_cast<FT_Face>( advanceFont->mFace );
if ( !face || !advanceFont->setCurrentSize( characterSize ) )
return 0.f;
FT_Int32 flags =
fontSetLoadOptions( advanceFont->mAntialiasing, advanceFont->mHinting ) | FT_LOAD_COLOR;
if ( FT_Load_Glyph( face, index, flags ) != 0 )
return 0.f;
Float advance =
static_cast<Float>( face->glyph->metrics.horiAdvance ) / static_cast<Float>( 1 << 6 );
if ( bold && !advanceFont->mIsBold && !advanceFont->mBoldAdvanceSameAsRegular )
advance += 1.f;
advances[key] = advance;
return advance;
}
static constexpr FT_Render_Mode fontSetRenderOptions( FT_Library library,
FontAntialiasing antialiasing,
FontHinting hinting,
@@ -1786,7 +1890,10 @@ bool FontTrueType::isFallbackFontEnabled() const {
}
void FontTrueType::setEnableFallbackFont( bool enableFallbackFont ) {
mEnableFallbackFont = enableFallbackFont;
if ( mEnableFallbackFont != enableFallbackFont ) {
mEnableFallbackFont = enableFallbackFont;
mGlyphAdvanceCache.clear();
}
}
bool FontTrueType::isSystemFallbackEnabled() const {
@@ -1794,7 +1901,10 @@ bool FontTrueType::isSystemFallbackEnabled() const {
}
void FontTrueType::setEnableSystemFallback( bool enableSystemFallback ) {
mEnableSystemFallback = enableSystemFallback;
if ( mEnableSystemFallback != enableSystemFallback ) {
mEnableSystemFallback = enableSystemFallback;
mGlyphAdvanceCache.clear();
}
}
bool FontTrueType::isEmojiFallbackEnabled() const {
@@ -1802,7 +1912,10 @@ bool FontTrueType::isEmojiFallbackEnabled() const {
}
void FontTrueType::setEnableEmojiFallback( bool enableEmojiFallback ) {
mEnableEmojiFallback = enableEmojiFallback;
if ( mEnableEmojiFallback != enableEmojiFallback ) {
mEnableEmojiFallback = enableEmojiFallback;
mGlyphAdvanceCache.clear();
}
}
const Uint32& FontTrueType::getFontInternalId() const {
@@ -1848,7 +1961,10 @@ bool FontTrueType::getBoldAdvanceSameAsRegular() const {
}
void FontTrueType::setBoldAdvanceSameAsRegular( bool boldAdvanceSameAsRegular ) {
mBoldAdvanceSameAsRegular = boldAdvanceSameAsRegular;
if ( mBoldAdvanceSameAsRegular != boldAdvanceSameAsRegular ) {
mBoldAdvanceSameAsRegular = boldAdvanceSameAsRegular;
mGlyphAdvanceCache.clear();
}
}
void FontTrueType::updateMonospaceState() const {
@@ -1858,96 +1974,40 @@ void FontTrueType::updateMonospaceState() const {
return;
}
mIsMonospaceCompletePending = false;
if ( mIsMonospaceComplete && mFontBold != nullptr ) {
if ( mIsMonospaceComplete && mFontBold ) {
mIsMonospaceComplete = mIsMonospaceComplete && mFontBold->isMonospace() &&
getGlyph( ' ', 10, false, false ).advance ==
mFontBold->getGlyph( ' ', 10, false, false ).advance;
getGlyphAdvance( ' ', 10 ) == mFontBold->getGlyphAdvance( ' ', 10 );
}
if ( mIsMonospaceComplete && mFontItalic != nullptr ) {
mIsMonospaceComplete = mIsMonospaceComplete && mFontItalic->isMonospace() &&
getGlyph( ' ', 10, false, false ).advance ==
mFontItalic->getGlyph( ' ', 10, false, false ).advance;
if ( mIsMonospaceComplete && mFontItalic ) {
mIsMonospaceComplete =
mIsMonospaceComplete && mFontItalic->isMonospace() &&
getGlyphAdvance( ' ', 10 ) == mFontItalic->getGlyphAdvance( ' ', 10 );
}
if ( mIsMonospaceComplete && mFontBoldItalic != nullptr ) {
mIsMonospaceComplete = mIsMonospaceComplete && mFontBoldItalic->isMonospace() &&
getGlyph( ' ', 10, false, false ).advance ==
mFontBoldItalic->getGlyph( ' ', 10, false, false ).advance;
if ( mIsMonospaceComplete && mFontBoldItalic ) {
mIsMonospaceComplete =
mIsMonospaceComplete && mFontBoldItalic->isMonospace() &&
getGlyphAdvance( ' ', 10 ) == mFontBoldItalic->getGlyphAdvance( ' ', 10 );
}
}
void FontTrueType::setBoldFont( FontTrueType* fontBold ) {
if ( fontBold == mFontBold )
return;
disconnectBoldFont();
void FontTrueType::setBoldFont( const FontTrueTypePtr& fontBold ) {
mFontBold = fontBold;
if ( mFontBold != nullptr ) {
mFontBoldCb = mFontBold->pushFontEventCallback( [this]( Uint32, Event event, Font* ) {
if ( event == Font::Event::Unload ) {
// Maybe we should recreate the page table
mFontBold = nullptr;
mFontBoldCb = 0;
}
} );
}
mGlyphAdvanceCache.clear();
updateMonospaceState();
}
void FontTrueType::setItalicFont( FontTrueType* fontItalic ) {
if ( fontItalic == mFontItalic )
return;
disconnectItalicFont();
void FontTrueType::setItalicFont( const FontTrueTypePtr& fontItalic ) {
mFontItalic = fontItalic;
if ( mFontItalic != nullptr ) {
mFontItalicCb = mFontItalic->pushFontEventCallback( [this]( Uint32, Event event, Font* ) {
if ( event == Font::Event::Unload ) {
// Maybe we should recreate the page table
mFontItalic = nullptr;
mFontItalicCb = 0;
}
} );
}
mGlyphAdvanceCache.clear();
updateMonospaceState();
}
void FontTrueType::setBoldItalicFont( FontTrueType* fontBoldItalic ) {
if ( fontBoldItalic == mFontBoldItalic )
return;
disconnectBoldItalicFont();
void FontTrueType::setBoldItalicFont( const FontTrueTypePtr& fontBoldItalic ) {
mFontBoldItalic = fontBoldItalic;
if ( mFontBoldItalic != nullptr ) {
mFontBoldItalicCb =
mFontBoldItalic->pushFontEventCallback( [this]( Uint32, Event event, Font* ) {
if ( event == Font::Event::Unload ) {
// Maybe we should recreate the page table
mFontBoldItalic = nullptr;
mFontBoldItalicCb = 0;
}
} );
}
mGlyphAdvanceCache.clear();
updateMonospaceState();
}
void FontTrueType::disconnectBoldFont() {
if ( mFontBoldCb != 0 && mFontBold != nullptr )
mFontBold->popFontEventCallback( mFontBoldCb );
mFontBold = nullptr;
mFontBoldCb = 0;
}
void FontTrueType::disconnectItalicFont() {
if ( mFontItalicCb != 0 && mFontItalic != nullptr )
mFontItalic->popFontEventCallback( mFontItalicCb );
mFontItalic = nullptr;
mFontItalicCb = 0;
}
void FontTrueType::disconnectBoldItalicFont() {
if ( mFontBoldItalicCb != 0 && mFontBoldItalic != nullptr )
mFontBoldItalic->popFontEventCallback( mFontBoldItalicCb );
mFontBoldItalic = nullptr;
mFontBoldItalicCb = 0;
}
bool FontTrueType::hasSvgGlyphs() const {
return mHasSvgGlyphs;
}
@@ -1988,6 +2048,7 @@ void FontTrueType::clearCache() {
mKeyCache.clear();
mKerningCache.clear();
mKerningGlyphCache.clear();
mGlyphAdvanceCache.clear();
Text::GlobalInvalidationId++;
}
+101 -1
View File
@@ -98,6 +98,35 @@ void ResourceCatalog::publishAtlas( std::string key, TextureAtlasPtr atlas ) {
previous.reset();
}
void ResourceCatalog::publishFont( ResourceKey key, FontPtr font ) {
publishFont( key.value(), std::move( font ) );
}
void ResourceCatalog::publishFont( std::string key, FontPtr font ) {
if ( key.empty() )
return;
if ( !font ) {
eraseFont( key );
return;
}
FontPtr previous;
String::HashType id = String::hash( key );
{
Lock lock( mMutex );
auto it = mFonts.find( key );
if ( it == mFonts.end() ) {
mFonts.emplace( std::move( key ), font );
mFontsById[id] = font;
return;
}
previous = std::move( it->second );
it->second = font;
mFontsById[id] = font;
}
previous.reset();
}
TexturePtr ResourceCatalog::findTexture( const ResourceKey& key ) const {
return findTexture( key.value() );
}
@@ -143,6 +172,31 @@ std::vector<TextureAtlasPtr> ResourceCatalog::getAtlases() const {
return atlases;
}
FontPtr ResourceCatalog::findFont( const ResourceKey& key ) const {
return findFont( key.value() );
}
FontPtr ResourceCatalog::findFont( const std::string& key ) const {
Lock lock( mMutex );
auto it = mFonts.find( key );
return it != mFonts.end() ? it->second : FontPtr{};
}
FontPtr ResourceCatalog::findFont( const String::HashType& id ) const {
Lock lock( mMutex );
auto it = mFontsById.find( id );
return it != mFontsById.end() ? it->second.lock() : FontPtr{};
}
std::vector<FontPtr> ResourceCatalog::getFonts() const {
std::vector<FontPtr> fonts;
Lock lock( mMutex );
fonts.reserve( mFonts.size() );
for ( const auto& font : mFonts )
fonts.emplace_back( font.second );
return fonts;
}
bool ResourceCatalog::erase( const ResourceKey& key ) {
return erase( key.value() );
}
@@ -204,28 +258,74 @@ bool ResourceCatalog::eraseAtlas( const std::string& key ) {
return true;
}
bool ResourceCatalog::eraseFont( const ResourceKey& key ) {
return eraseFont( key.value() );
}
bool ResourceCatalog::eraseFont( const std::string& key ) {
FontPtr font;
{
Lock lock( mMutex );
auto it = mFonts.find( key );
if ( it == mFonts.end() )
return false;
font = std::move( it->second );
mFonts.erase( it );
auto idIt = mFontsById.find( String::hash( key ) );
if ( idIt != mFontsById.end() )
mFontsById.erase( idIt );
}
font.reset();
return true;
}
bool ResourceCatalog::eraseFont( Font* font ) {
if ( !font )
return false;
FontPtr removed;
{
Lock lock( mMutex );
auto it = mFonts.find( font->getName() );
if ( it == mFonts.end() || it->second.get() != font )
return false;
removed = std::move( it->second );
mFonts.erase( it );
auto idIt = mFontsById.find( font->getId() );
if ( idIt != mFontsById.end() )
mFontsById.erase( idIt );
}
removed.reset();
return true;
}
void ResourceCatalog::clear() {
UnorderedMap<std::string, TexturePtr> textures;
UnorderedMap<std::string, DrawablePtr> drawables;
UnorderedMap<String::HashType, DrawableWeakPtr> drawablesById;
UnorderedMap<std::string, TextureAtlasPtr> atlases;
UnorderedMap<std::string, FontPtr> fonts;
UnorderedMap<String::HashType, FontWeakPtr> fontsById;
{
Lock lock( mMutex );
textures = std::move( mTextures );
drawables = std::move( mDrawables );
drawablesById = std::move( mDrawablesById );
atlases = std::move( mAtlases );
fonts = std::move( mFonts );
fontsById = std::move( mFontsById );
}
textures.clear();
drawables.clear();
drawablesById.clear();
atlases.clear();
fonts.clear();
fontsById.clear();
}
std::size_t ResourceCatalog::size() const {
Lock lock( mMutex );
return mTextures.size() + mDrawables.size() + mAtlases.size();
return mTextures.size() + mDrawables.size() + mAtlases.size() + mFonts.size();
}
}} // namespace EE::Graphics
+106 -1
View File
@@ -1,5 +1,6 @@
#include <algorithm>
#include <eepp/core/string.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/sprite.hpp>
#include <eepp/system/filesystem.hpp>
@@ -15,7 +16,37 @@ ResourceScopePtr ResourceScope::New() {
return ResourceScopePtr( eeNew( ResourceScope, () ), ResourceDeleter<ResourceScope>() );
}
ResourceScope::ResourceScope() : mLocalCatalog( ResourceCatalog::New() ) {}
ResourceScope::ResourceScope() : mLocalCatalog( ResourceCatalog::New() ), mFontService( *this ) {}
ResourceScope::~ResourceScope() {
for ( const FontPtr& font : mLocalCatalog->getFonts() )
detachFontService( font );
}
void ResourceScope::attachFontService( const FontPtr& font ) {
if ( font && font->getType() == FontType::TTF )
static_cast<FontTrueType*>( font.get() )->setFontService( &mFontService );
}
void ResourceScope::detachFontService( const FontPtr& font ) {
if ( font ) {
mFontService.onFontRemoved( font.get() );
if ( font->getType() != FontType::TTF )
return;
auto* ttf = static_cast<FontTrueType*>( font.get() );
if ( ttf->getFontService() == &mFontService ) {
ttf->setFontService( nullptr );
}
}
}
FontService& ResourceScope::getFontService() {
return mFontService;
}
const FontService& ResourceScope::getFontService() const {
return mFontService;
}
TexturePtr ResourceScope::findTexture( const ResourceKey& key ) const {
return findTexture( key.value() );
@@ -75,6 +106,42 @@ std::vector<TextureAtlasPtr> ResourceScope::getAtlases() const {
return atlases;
}
FontPtr ResourceScope::findFont( const ResourceKey& key ) const {
return findFont( key.value() );
}
FontPtr ResourceScope::findFont( const std::string& key ) const {
if ( FontPtr font = mLocalCatalog->findFont( key ) )
return font;
Lock lock( mMutex );
for ( const ResourceCatalogPtr& catalog : mImports ) {
if ( FontPtr font = catalog->findFont( key ) )
return font;
}
return {};
}
FontPtr ResourceScope::findFont( const String::HashType& id ) const {
if ( FontPtr font = mLocalCatalog->findFont( id ) )
return font;
Lock lock( mMutex );
for ( const ResourceCatalogPtr& catalog : mImports ) {
if ( FontPtr font = catalog->findFont( id ) )
return font;
}
return {};
}
std::vector<FontPtr> ResourceScope::getFonts() const {
std::vector<FontPtr> fonts = mLocalCatalog->getFonts();
Lock lock( mMutex );
for ( const ResourceCatalogPtr& catalog : mImports ) {
std::vector<FontPtr> imported = catalog->getFonts();
fonts.insert( fonts.end(), imported.begin(), imported.end() );
}
return fonts;
}
std::vector<TextureRegionPtr>
ResourceScope::findTextureRegionsByPattern( const std::string& name, const std::string& extension,
TextureAtlas* searchInTextureAtlas ) const {
@@ -232,6 +299,18 @@ void ResourceScope::publishLocalAtlas( std::string key, TextureAtlasPtr atlas )
mLocalCatalog->publishAtlas( std::move( key ), std::move( atlas ) );
}
void ResourceScope::publishLocalFont( ResourceKey key, FontPtr font ) {
publishLocalFont( key.value(), std::move( font ) );
}
void ResourceScope::publishLocalFont( std::string key, FontPtr font ) {
FontPtr replaced = mLocalCatalog->findFont( key );
if ( replaced && replaced != font )
detachFontService( replaced );
attachFontService( font );
mLocalCatalog->publishFont( std::move( key ), std::move( font ) );
}
bool ResourceScope::eraseLocal( const ResourceKey& key ) {
return mLocalCatalog->erase( key );
}
@@ -256,7 +335,33 @@ bool ResourceScope::eraseLocalAtlas( const std::string& key ) {
return mLocalCatalog->eraseAtlas( key );
}
bool ResourceScope::eraseLocalFont( const ResourceKey& key ) {
return eraseLocalFont( key.value() );
}
bool ResourceScope::eraseLocalFont( const std::string& key ) {
FontPtr font = mLocalCatalog->findFont( key );
if ( !font )
return false;
detachFontService( font );
return mLocalCatalog->eraseFont( key );
}
bool ResourceScope::eraseLocalFont( Font* font ) {
if ( !font )
return false;
FontPtr handle = mLocalCatalog->findFont( font->getId() );
if ( handle.get() != font )
return false;
if ( !mLocalCatalog->eraseFont( font ) )
return false;
detachFontService( handle );
return true;
}
void ResourceScope::clearLocal() {
for ( const FontPtr& font : mLocalCatalog->getFonts() )
detachFontService( font );
mLocalCatalog->clear();
}
+1 -1
View File
@@ -1,8 +1,8 @@
#include <algorithm>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/linewrap.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/richtext.hpp>
namespace EE { namespace Graphics {
+17 -15
View File
@@ -1,6 +1,6 @@
#include <algorithm>
#include <cmath>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/pixeldensity.hpp>
@@ -341,11 +341,12 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
String::StringBaseType prevChar = 0;
bool isBold = ( style & Text::Bold ) != 0;
bool isItalic = ( style & Text::Italic ) != 0;
bool fallbacksToColorEmoji =
font && font->getType() == FontType::TTF &&
!static_cast<FontTrueType*>( font )->isColorEmojiFont() &&
FontManager::instance()->getColorEmojiFont() != nullptr &&
FontManager::instance()->getColorEmojiFont()->getType() == FontType::TTF;
FontTrueType* trueTypeFont =
font && font->getType() == FontType::TTF ? static_cast<FontTrueType*>( font ) : nullptr;
FontService* fontService = trueTypeFont ? trueTypeFont->getFontService() : nullptr;
bool fallbacksToColorEmoji = trueTypeFont && !trueTypeFont->isColorEmojiFont() && fontService &&
fontService->getColorEmojiFont() != nullptr &&
fontService->getColorEmojiFont()->getType() == FontType::TTF;
bool isMonospace = font && ( font->isMonospace() ||
( font->getType() == FontType::TTF &&
static_cast<FontTrueType*>( font )->isIdentifiedAsMonospace() &&
@@ -355,12 +356,14 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
Float height = font->getLineSpacing( fontSize );
Sizef size{ 0, height };
size_t ssize = string.size();
if ( ssize == 0 )
return size;
BatchRenderer* BR = GlobalBatchRenderer::instance();
const TexturePtr& fontTexture = font->getTexture( fontSize );
Float tabAlign = 0;
GlyphDrawable* spaceGlyph = nullptr;
GlyphDrawable* tabGlyph = nullptr;
Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance;
Float hspace = font->getGlyphAdvance( ' ', fontSize, isBold, isItalic );
std::optional<Float> tabOffset{ whitespaceDisplayConfig.tabOffset };
if ( whitespaceDisplayConfig.tabDisplayCharacter )
tabGlyph = font->getGlyphDrawable( whitespaceDisplayConfig.tabDisplayCharacter, fontSize );
@@ -640,9 +643,10 @@ void Text::create( Font* font, const String& text, Color FontColor, Color FontSh
void Text::checkColorEmojis() {
mContainsColorEmoji = false;
if ( mFontStyleConfig.Font && FontManager::instance()->getColorEmojiFont() != nullptr ) {
if ( mFontStyleConfig.Font->getType() == FontType::TTF ) {
FontTrueType* fontTrueType = static_cast<FontTrueType*>( mFontStyleConfig.Font );
if ( mFontStyleConfig.Font && mFontStyleConfig.Font->getType() == FontType::TTF ) {
FontTrueType* fontTrueType = static_cast<FontTrueType*>( mFontStyleConfig.Font );
FontService* fontService = fontTrueType->getFontService();
if ( fontService && fontService->getColorEmojiFont() != nullptr ) {
if ( fontTrueType->isColorEmojiFont() || !fontTrueType->isEmojiFont() )
mContainsColorEmoji = Font::containsEmojiCodePoint( mString );
}
@@ -2963,11 +2967,9 @@ SmallVector<Rectf> Text::getSelectionRects( TextSelectionRange range ) {
size_t startLine = findVisualLineFromCharIndex( range.start );
size_t endLine = findVisualLineFromCharIndex( range.end );
Float hspace =
mFontStyleConfig.Font
->getGlyph( ' ', mFontStyleConfig.CharacterSize, mFontStyleConfig.Style & Text::Bold,
mFontStyleConfig.Style & Text::Italic )
.advance;
Float hspace = mFontStyleConfig.Font->getGlyphAdvance( ' ', mFontStyleConfig.CharacterSize,
mFontStyleConfig.Style & Text::Bold,
mFontStyleConfig.Style & Text::Italic );
Float vspace = getLineSpacing();
for ( size_t i = startLine; i <= endLine; ++i ) {
+29 -9
View File
@@ -13,7 +13,12 @@
namespace EE::Graphics {
using LRULayoutCache = LRUCache<8192, Uint64, TextLayout::Cache>;
struct LayoutCacheEntry {
Font* sourceFont{ nullptr };
TextLayout::Cache layout;
};
using LRULayoutCache = LRUCache<8192, Uint64, LayoutCacheEntry>;
#ifdef EE_TEXT_SHAPER_ENABLED
@@ -236,15 +241,30 @@ static inline Uint64 textLayoutHash( const String::View& string, Font* font,
std::hash<Float>()( initialXOffset ) );
}
static LRULayoutCache& getLayoutCache( bool invalidate = false ) {
static LRULayoutCache& getLayoutCache( bool invalidate = false, Font* font = nullptr ) {
static LRULayoutCache sLayoutCache;
if ( invalidate )
sLayoutCache.clear();
if ( invalidate ) {
if ( !font ) {
sLayoutCache.clear();
} else {
sLayoutCache.eraseIf( [font]( Uint64, const LayoutCacheEntry& entry ) {
if ( !entry.layout || entry.sourceFont == font )
return true;
for ( const ShapedTextParagraph& paragraph : entry.layout->paragraphs ) {
for ( const ShapedGlyph& glyph : paragraph.shapedGlyphs ) {
if ( glyph.font == font )
return true;
}
}
return false;
} );
}
}
return sLayoutCache;
}
void TextLayout::clearLayoutCache() {
getLayoutCache( true );
void TextLayout::clearLayoutCache( Font* font ) {
getLayoutCache( true, font );
}
TextLayout::Cache TextLayout::layout( const String::View& string, Font* font,
@@ -270,13 +290,13 @@ TextLayout::Cache TextLayout::layout( const String::View& string, Font* font,
auto cacheHit = getLayoutCache().get( hash );
if ( cacheHit.has_value() )
return *cacheHit;
return cacheHit->layout;
}
bool bold = ( style & Text::Bold ) != 0;
bool italic = ( style & Text::Italic ) != 0;
Uint32 spaceGlyphIndex = 0;
Float hspace = font->getGlyph( ' ', characterSize, bold, italic, outlineThickness ).advance;
Float hspace = font->getGlyphAdvance( ' ', characterSize, bold, italic, outlineThickness );
Float vspace = font->getLineSpacing( characterSize );
Vector2f pen{ initialXOffset, 0 };
Float maxWidth = 0;
@@ -523,7 +543,7 @@ TextLayout::Cache TextLayout::layout( const String::View& string, Font* font,
characterSize, style, tabWidth, outlineThickness, hspace );
}
getLayoutCache().put( hash, resultPtr );
getLayoutCache().put( hash, { font, resultPtr } );
return resultPtr;
}
-1
View File
@@ -1,6 +1,5 @@
#include <SOIL2/src/SOIL2/SOIL2.h>
#include <SOIL2/src/SOIL2/stb_image.h>
#include <algorithm>
#include <atomic>
#include <eepp/graphics/renderer/openglext.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
+19 -20
View File
@@ -1,8 +1,8 @@
#include <eepp/graphics/circledrawable.hpp>
#include <eepp/graphics/convexshapedrawable.hpp>
#include <eepp/graphics/drawable.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/rectangledrawable.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/triangledrawable.hpp>
#include <eepp/system/log.hpp>
#include <eepp/system/luapattern.hpp>
@@ -151,7 +151,7 @@ bool DrawableImageParser::exists( const std::string& name ) const {
}
DrawablePtr DrawableImageParser::createDrawable( const std::string& value, const Sizef& size,
UINode* node ) {
UINode* node ) {
FunctionString functionType = FunctionString::parse( value );
if ( "none" == value )
@@ -183,7 +183,7 @@ void DrawableImageParser::addParser( const std::string& name,
void DrawableImageParser::registerBaseParsers() {
// Shared parsing logic for linear-gradient and repeating-linear-gradient
auto parseGradient = []( const FunctionString& functionType, UINode* node,
bool repeating ) -> DrawablePtr {
bool repeating ) -> DrawablePtr {
const auto& params( functionType.getParameters() );
if ( params.size() < 2 )
return {};
@@ -459,14 +459,14 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["repeating-linear-gradient"] = [parseGradient]( const FunctionString& functionType,
const Sizef& /*size*/,
UINode* node ) -> DrawablePtr {
const Sizef& /*size*/,
UINode* node ) -> DrawablePtr {
return parseGradient( functionType, node, true );
};
// Shared parsing logic for radial-gradient and repeating-radial-gradient
auto parseRadialGradient = []( const FunctionString& functionType, UINode* node,
bool repeating ) -> DrawablePtr {
bool repeating ) -> DrawablePtr {
const auto& params( functionType.getParameters() );
if ( params.size() < 2 )
return {};
@@ -681,13 +681,13 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["repeating-radial-gradient"] = [parseRadialGradient]( const FunctionString& functionType,
const Sizef& /*size*/,
UINode* node ) -> DrawablePtr {
const Sizef& /*size*/,
UINode* node ) -> DrawablePtr {
return parseRadialGradient( functionType, node, true );
};
mFuncs["circle"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
if ( functionType.getParameters().size() < 1 ) {
return {};
}
@@ -717,7 +717,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["rectangle"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
if ( functionType.getParameters().size() < 1 ) {
return {};
}
@@ -776,7 +776,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["triangle"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
if ( functionType.getParameters().size() < 2 ) {
return {};
}
@@ -843,7 +843,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["poly"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
if ( functionType.getParameters().size() < 2 ) {
return {};
}
@@ -899,7 +899,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["url"] = []( const FunctionString& functionType, const Sizef& /*size*/,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
if ( functionType.getParameters().size() < 1 )
return {};
const auto& param = functionType.getParameters().at( 0 );
@@ -915,8 +915,7 @@ void DrawableImageParser::registerBaseParsers() {
cparam += ',';
cparam += functionType.getParameters().at( i );
}
DrawablePtr drawable =
node->getUISceneNode()->getDrawableResolver().resolve( cparam );
DrawablePtr drawable = node->getUISceneNode()->getDrawableResolver().resolve( cparam );
return drawable;
}
DrawablePtr drawable = node->getUISceneNode()->getDrawableResolver().resolve( param );
@@ -924,7 +923,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["icon"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
auto* uiScene = node->getUISceneNode();
const auto& params = functionType.getParameters();
if ( params.size() < 2 )
@@ -935,11 +934,11 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["glyph"] = []( const FunctionString& functionType, const Sizef& size,
UINode* node ) -> DrawablePtr {
UINode* node ) -> DrawablePtr {
const auto& params = functionType.getParameters();
if ( params.size() < 3 )
return nullptr;
Font* font = FontManager::instance()->getByName( params[0] );
Font* font = node->getUISceneNode()->getResourceScope()->findFont( params[0] ).get();
if ( font == nullptr )
return nullptr;
Uint32 codePoint = 0;
@@ -955,8 +954,8 @@ void DrawableImageParser::registerBaseParsers() {
} else if ( String::fromString( value, buffer ) ) {
codePoint = value;
}
Drawable* drawable = font->getGlyphDrawable(
codePoint, node->convertLength( params[1], size.getWidth() ) );
Drawable* drawable =
font->getGlyphDrawable( codePoint, node->convertLength( params[1], size.getWidth() ) );
return drawable ? drawable->clone() : DrawablePtr{};
};
}
+49 -18
View File
@@ -1,7 +1,7 @@
#include <algorithm>
#include <cctype>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/scenemanager.hpp>
#include <eepp/system/filesystem.hpp>
@@ -267,6 +267,7 @@ UIFontPickerDialog::~UIFontPickerDialog() {
mColorPicker = nullptr;
mColorPickerCloseCb = 0;
clearBrowseDialog();
clearPreviewFont();
}
Uint32 UIFontPickerDialog::getType() const {
@@ -294,7 +295,7 @@ void UIFontPickerDialog::setTheme( UITheme* theme ) {
if ( mButtonBrowse ) {
if ( DrawablePtr icon = getUISceneNode()->findIconDrawable( "document-open",
PixelDensity::dpToPxI( 16 ) ) )
PixelDensity::dpToPxI( 16 ) ) )
mButtonBrowse->setIcon( std::move( icon ) );
}
@@ -438,7 +439,7 @@ void UIFontPickerDialog::loadFonts() {
void UIFontPickerDialog::setFonts( std::vector<FontDesc> fonts ) {
FontDesc selectedFont = mSelection.font;
mergeFontManagerFonts( fonts );
mergeLoadedFonts( fonts );
for ( const auto& font : mFonts ) {
if ( std::find_if( fonts.begin(), fonts.end(), [&]( const FontDesc& desc ) {
return desc.sameFile( font );
@@ -471,21 +472,23 @@ void UIFontPickerDialog::sortFonts() {
} );
}
void UIFontPickerDialog::mergeFontManagerFonts( std::vector<FontDesc>& fonts ) {
FontManager::instance()->each( [&]( const auto& res ) {
if ( res.second == nullptr || res.second->getType() != FontType::TTF )
return;
void UIFontPickerDialog::mergeLoadedFonts( std::vector<FontDesc>& fonts ) {
if ( !getUISceneNode() )
return;
for ( const FontPtr& font : getUISceneNode()->getResourceScope()->getFonts() ) {
if ( font == nullptr || font->getType() != FontType::TTF )
continue;
FontDesc desc;
if ( !static_cast<FontTrueType*>( res.second )->getFontDesc( desc ) )
return;
if ( !static_cast<FontTrueType*>( font.get() )->getFontDesc( desc ) )
continue;
mLoadedFontKeys.insert( desc.getFileKey() );
if ( std::find_if( fonts.begin(), fonts.end(), [&]( const FontDesc& font ) {
return font.sameFile( desc );
} ) == fonts.end() )
fonts.push_back( desc );
} );
}
}
void UIFontPickerDialog::updateFontTags() {
@@ -628,10 +631,24 @@ void UIFontPickerDialog::updatePreview() {
if ( !mPreviewText )
return;
FontTrueType* font = FontManager::instance()->getOrLoadSystemFallbackFont( mSelection.font );
if ( font ) {
mPreviewText->setFont( font );
mPreviewInput->setFont( font );
if ( !mPreviewTextDefaultFont )
mPreviewTextDefaultFont = mPreviewText->getFont();
if ( !mPreviewInputDefaultFont )
mPreviewInputDefaultFont = mPreviewInput->getFont();
FontDesc previewDesc;
const bool previewMatchesSelection = mPreviewFont && mPreviewFont->getFontDesc( previewDesc ) &&
previewDesc.sameFile( mSelection.font );
if ( !previewMatchesSelection && !mSelection.font.path.empty() && getUISceneNode() ) {
FontTrueTypePtr font =
getUISceneNode()->getResourceScope()->getFontService().loadSystemFont(
mSelection.font );
if ( font ) {
mPreviewText->setFont( font.get() );
mPreviewInput->setFont( font.get() );
clearPreviewFont();
mPreviewFont = std::move( font );
}
}
mPreviewText->setFontSize( PixelDensity::dpToPxI( mSelection.size * 2 ) );
@@ -657,6 +674,17 @@ void UIFontPickerDialog::updatePreview() {
}
}
void UIFontPickerDialog::clearPreviewFont() {
if ( !mPreviewFont )
return;
if ( mPreviewText && mPreviewTextDefaultFont && mPreviewText->getFont() == mPreviewFont.get() )
mPreviewText->setFont( mPreviewTextDefaultFont );
if ( mPreviewInput && mPreviewInputDefaultFont &&
mPreviewInput->getFont() == mPreviewFont.get() )
mPreviewInput->setFont( mPreviewInputDefaultFont );
mPreviewFont.reset();
}
void UIFontPickerDialog::selectInitialRows() {
mSizeModel = ItemListModel<Uint32>::create( mSizes );
mSizeList->setModel( mSizeModel );
@@ -782,18 +810,21 @@ bool UIFontPickerDialog::addExternalFont( const std::string& path, Uint32 faceIn
const std::string fontName(
FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) ) );
FontTrueType* font = FontTrueType::New( fontName );
if ( !getUISceneNode() )
return false;
ResourceScope& resourceScope = *getUISceneNode()->getResourceScope();
FontTrueTypePtr font = FontTrueType::New( fontName, resourceScope );
if ( !font || !font->loadFromFile( path, faceIndex ) ) {
eeSAFE_DELETE( font );
resourceScope.eraseLocalFont( font.get() );
return false;
}
FontDesc desc;
if ( !font->getFontDesc( desc ) ) {
eeSAFE_DELETE( font );
resourceScope.eraseLocalFont( font.get() );
return false;
}
eeSAFE_DELETE( font );
resourceScope.eraseLocalFont( font.get() );
mLoadedFontKeys.insert( desc.getFileKey() );
mFonts.push_back( desc );
+10 -7
View File
@@ -59,17 +59,20 @@ UIApplication::UIApplication( const WindowSettings& windowSettings, const Settin
if ( !appSettings.loadBaseResources )
return;
Font* font = appSettings.baseFont
? appSettings.baseFont
: FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
FontTrueTypePtr loadedBaseFont;
if ( !appSettings.baseFont )
loadedBaseFont =
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
Font* font = appSettings.baseFont ? appSettings.baseFont : loadedBaseFont.get();
if ( font && font->getType() == FontType::TTF )
FontFamily::loadFromRegular( static_cast<FontTrueType*>( font ) );
Font* monospaceFont = appSettings.monospaceFont
? appSettings.monospaceFont
: FontTrueType::New( "monospace", "assets/fonts/DejaVuSansMono.ttf" );
FontTrueTypePtr loadedMonospaceFont;
if ( !appSettings.monospaceFont )
loadedMonospaceFont = FontTrueType::New( "monospace", "assets/fonts/DejaVuSansMono.ttf" );
Font* monospaceFont =
appSettings.monospaceFont ? appSettings.monospaceFont : loadedMonospaceFont.get();
if ( monospaceFont && monospaceFont->getType() == FontType::TTF ) {
static_cast<FontTrueType*>( monospaceFont )->setEnableDynamicMonospace( true );
+2 -2
View File
@@ -1,10 +1,10 @@
#include "eepp/ui/uistyle.hpp"
#include <algorithm>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/scene/actions/close.hpp>
#include <eepp/scene/actions/scale.hpp>
#include <eepp/scene/actions/sequence.hpp>
@@ -138,7 +138,7 @@ const MouseBindings::ShortcutMap UICodeEditor::getDefaultMousebindings() {
UICodeEditor::UICodeEditor( const std::string& elementTag, const bool& autoRegisterBaseCommands,
const bool& autoRegisterBaseKeybindings ) :
UIWidget( elementTag ),
mFont( FontManager::instance()->getByName( "monospace" ) ),
mFont( getUISceneNode()->getResourceScope()->findFont( "monospace" ).get() ),
mDoc( std::make_shared<TextDocument>() ),
mDocView( mDoc, mFontStyleConfig, { .tabStops = mTabStops } ),
mBlinkTime( Seconds( 0.5f ) ),
+2 -2
View File
@@ -1,9 +1,9 @@
#include <algorithm>
#include <eepp/audio/listener.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/action.hpp>
#include <eepp/scene/actions/actions.hpp>
@@ -52,7 +52,7 @@ UIConsole::UIConsole( Font* font, const bool& makeDefaultCommands, const bool& a
mFontStyleConfig.Font = font;
if ( nullptr == font )
mFontStyleConfig.Font = FontManager::instance()->getByName( "monospace" );
mFontStyleConfig.Font = getUISceneNode()->getResourceScope()->findFont( "monospace" ).get();
mMaxLogLines = maxLogLines;
-1
View File
@@ -1,6 +1,5 @@
#include <algorithm>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/ui/css/propertydefinition.hpp>
#include <eepp/ui/uiitemcontainer.hpp>
-1
View File
@@ -1,7 +1,6 @@
#include <algorithm>
#include <cmath>
#include <eepp/core/debug.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/scenemanager.hpp>
+47 -37
View File
@@ -1,6 +1,6 @@
#include <algorithm>
#include <eepp/core/string.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/graphics/text.hpp>
@@ -129,11 +129,11 @@ static void refreshWebViewDocumentLayoutAfterStyleChange( UIWidget* root ) {
}
}
UISceneNode* UISceneNode::New( EE::Window::Window* window ) {
return eeNew( UISceneNode, ( window ) );
UISceneNode* UISceneNode::New( EE::Window::Window* window, bool importDefaultResources ) {
return eeNew( UISceneNode, ( window, importDefaultResources ) );
}
UISceneNode::UISceneNode( EE::Window::Window* window ) :
UISceneNode::UISceneNode( EE::Window::Window* window, bool importDefaultResources ) :
SceneNode( window ),
mRoot( NULL ),
mIsLoading( false ),
@@ -141,10 +141,14 @@ UISceneNode::UISceneNode( EE::Window::Window* window ) :
mUIThemeManager( UIThemeManager::New() ),
mUIIconThemeManager( UIIconThemeManager::New()->setFallbackThemeManager( mUIThemeManager ) ),
mAsyncResourceLoadState( std::make_shared<AsyncResourceLoadState>() ),
mImportDefaultResources( importDefaultResources ),
mResourceScope( ResourceScope::New() ),
mDrawableResolver( *this ),
mWebResourceCache( WebResourceCache::New() ),
mKeyBindings( mWindow->getInput() ) {
if ( mImportDefaultResources )
mResourceScope->importCatalog( defaultResourceScope().getLocalCatalog() );
// Reset size since the SceneNode already set it but needs to set the size from zero to emit
// the required events to its children.
mSize = Sizef();
@@ -764,6 +768,8 @@ const ResourceScopePtr& UISceneNode::getResourceScope() const {
UISceneNode* UISceneNode::setResourceScope( ResourceScopePtr resourceScope ) {
mResourceScope = resourceScope ? std::move( resourceScope ) : ResourceScope::New();
if ( mImportDefaultResources )
mResourceScope->importCatalog( defaultResourceScope().getLocalCatalog() );
mUIThemeManager->setResourceScope( mResourceScope );
return this;
}
@@ -1455,7 +1461,7 @@ UIIcon* UISceneNode::findIcon( const std::string& iconName ) {
}
DrawablePtr UISceneNode::findIconDrawable( const std::string& iconName,
const size_t& drawableSize ) {
const size_t& drawableSize ) {
UIIcon* icon = findIcon( iconName );
return icon ? icon->createDrawable( drawableSize ) : DrawablePtr{};
}
@@ -1530,7 +1536,7 @@ void UISceneNode::loadGlyphIcon( const StyleSheetStyleVector& styles ) {
CSS::StyleSheetProperty glyphProp( *glyph );
if ( !familyProp.isEmpty() && !nameProp.isEmpty() && !glyphProp.isEmpty() ) {
Font* fontSearch = FontManager::instance()->getByName( familyProp.getValue() );
Font* fontSearch = mResourceScope->findFont( familyProp.getValue() ).get();
if ( nullptr == fontSearch )
continue;
@@ -1675,11 +1681,11 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles, URI baseUR
fontStyle, static_cast<Uint32>( fontWeight ) );
};
auto registerLoadedFont = [this, authorFamily, fontStyle,
fontWeight]( FontTrueType* font ) {
fontWeight]( FontTrueTypePtr font ) {
if ( font == nullptr || !font->loaded() )
return false;
font->setVariableFontWeight( fontWeight );
registerFontFaceAlias( authorFamily, fontStyle, fontWeight, font );
registerFontFaceAlias( authorFamily, fontStyle, fontWeight, font.get() );
mFontFaces.push_back( font );
mRoot->reloadFontFamily();
return true;
@@ -1706,12 +1712,13 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles, URI baseUR
if ( isBase64 && !data.empty() ) {
std::string decoded;
Base64::decode( data, decoded );
FontTrueType* font = FontTrueType::New(
makeInternalFontName( authorFamily, fontStyle, fontWeight ) );
FontTrueTypePtr font = FontTrueType::New(
makeInternalFontName( authorFamily, fontStyle, fontWeight ),
*mResourceScope );
if ( font->loadFromMemory( &decoded[0], decoded.size() ) ) {
registerLoadedFont( font );
} else
eeSAFE_DELETE( font );
mResourceScope->eraseLocalFont( font.get() );
}
}
return;
@@ -1723,14 +1730,14 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles, URI baseUR
if ( String::startsWith( path, "file://" ) ) {
std::string filePath( resolvedURI.getFSPath() );
FontTrueType* font =
FontTrueType::New( makeInternalFontName( authorFamily, fontStyle, fontWeight ) );
FontTrueTypePtr font = FontTrueType::New(
makeInternalFontName( authorFamily, fontStyle, fontWeight ), *mResourceScope );
if ( font->loadFromFile( filePath ) ) {
registerLoadedFont( font );
runOnMainThread( [this] { mRoot->reloadFontFamily(); } );
} else
eeSAFE_DELETE( font );
mResourceScope->eraseLocalFont( font.get() );
} else if ( String::startsWith( path, "http://" ) ||
String::startsWith( path, "https://" ) ) {
std::string internalFontName(
@@ -1755,17 +1762,18 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles, URI baseUR
resourceState, resourceGeneration,
[fontData = std::move( fontData ), internalFontName, authorFamily,
fontStyle, fontWeight]( UISceneNode* scene ) mutable {
FontTrueType* font = FontTrueType::New( internalFontName );
FontTrueTypePtr font =
FontTrueType::New( internalFontName, *scene->mResourceScope );
if ( font->loadFromMemory( &fontData[0], fontData.size() ) &&
font->loaded() ) {
font->setVariableFontWeight( fontWeight );
scene->registerFontFaceAlias( authorFamily, fontStyle, fontWeight,
font );
font.get() );
scene->mFontFaces.push_back( font );
if ( scene->mRoot )
scene->mRoot->reloadFontFamily();
} else {
eeSAFE_DELETE( font );
scene->mResourceScope->eraseLocalFont( font.get() );
}
} );
} else {
@@ -1781,14 +1789,14 @@ void UISceneNode::loadFontFaces( const StyleSheetStyleVector& styles, URI baseUR
}
} );
} else if ( VFS::instance()->fileExists( path ) ) {
FontTrueType* font =
FontTrueType::New( makeInternalFontName( authorFamily, fontStyle, fontWeight ) );
FontTrueTypePtr font = FontTrueType::New(
makeInternalFontName( authorFamily, fontStyle, fontWeight ), *mResourceScope );
IOStream* stream = VFS::instance()->getFileFromPath( path );
if ( font->loadFromStream( *stream ) ) {
registerLoadedFont( font );
} else
eeSAFE_DELETE( font );
mResourceScope->eraseLocalFont( font.get() );
}
};
@@ -2204,7 +2212,6 @@ void UISceneNode::invalidate( Node* invalidator ) {
Font* UISceneNode::getFontFromNamesList( std::string_view names, Uint32 fontStyle,
FontWeight weight ) const {
FontManager* fm = FontManager::instance();
Font* font = nullptr;
String::readBySeparatorStoppable(
names,
@@ -2222,7 +2229,7 @@ Font* UISceneNode::getFontFromNamesList( std::string_view names, Uint32 fontStyl
if ( fontStyle )
fontFamily += "#" + Text::styleFlagToString( fontStyle );
font = fm->getByName( fontFamily );
font = mResourceScope->findFont( fontFamily ).get();
// Remove the font style part (ex: `Arial#bold` to `Arial`)
// We need this for SystemFontResolver::genericFamilyFromName
@@ -2243,7 +2250,7 @@ Font* UISceneNode::getFontFromNamesList( std::string_view names, Uint32 fontStyl
if ( fontStyle )
fontFamily += "#" + Text::styleFlagToString( fontStyle );
font = fm->getByName( fontFamily );
font = mResourceScope->findFont( fontFamily ).get();
}
if ( font == nullptr && SystemFontResolver::isEnabled() ) {
@@ -2258,15 +2265,16 @@ Font* UISceneNode::getFontFromNamesList( std::string_view names, Uint32 fontStyl
if ( fontStyle )
family += "#" + Text::styleFlagToString( fontStyle );
if ( ( font = fm->getByName( family ) ) )
if ( ( font = mResourceScope->findFont( family ).get() ) )
return true;
FontTrueType* ttf = FontTrueType::New( family, desc.path, desc.faceIndex );
FontTrueTypePtr ttf =
FontTrueType::New( family, desc.path, desc.faceIndex, *mResourceScope );
if ( ttf && ttf->loaded() ) {
font = ttf;
font = ttf.get();
Uint32 weightStyle = fontStyle & ( Text::Bold | Text::Italic );
if ( weightStyle ) {
Font* regular = fm->getByName( desc.family );
Font* regular = mResourceScope->findFont( desc.family ).get();
if ( regular && regular != font &&
regular->getType() == FontType::TTF ) {
auto* regularFT = static_cast<FontTrueType*>( regular );
@@ -2309,8 +2317,8 @@ void UISceneNode::clearFontFaces() {
if ( mRoot )
mRoot->reloadFontFamily();
for ( auto& font : mFontFaces )
FontManager::instance()->remove( font );
for ( const FontPtr& font : mFontFaces )
mResourceScope->eraseLocalFont( font.get() );
mFontFaces.clear();
}
@@ -2348,7 +2356,7 @@ void UISceneNode::loadFontStyleVariants( Font* font, const std::string& family )
return;
auto* ft = static_cast<FontTrueType*>( font );
auto loadVariant = [family]( FontWeight weight, bool italic ) -> FontTrueType* {
auto loadVariant = [this, family]( FontWeight weight, bool italic ) -> FontTrueTypePtr {
Uint32 style = 0;
if ( italic )
style |= Text::Italic;
@@ -2357,9 +2365,10 @@ void UISceneNode::loadFontStyleVariants( Font* font, const std::string& family )
std::string queryFamily = family;
if ( style )
queryFamily += "#" + Text::styleFlagToString( style );
Font* existing = FontManager::instance()->getByName( queryFamily );
FontPtr existingHandle = mResourceScope->findFont( queryFamily );
Font* existing = existingHandle.get();
if ( existing && existing->getType() == FontType::TTF )
return static_cast<FontTrueType*>( existing );
return std::static_pointer_cast<FontTrueType>( existingHandle );
FontDesc desc = SystemFontResolver::instance()->resolveGeneric(
SystemFontResolver::genericFamilyFromName( family ), weight, italic );
@@ -2373,23 +2382,24 @@ void UISceneNode::loadFontStyleVariants( Font* font, const std::string& family )
if ( desc.path.empty() )
return nullptr;
auto* ttf = FontTrueType::New( queryFamily, desc.path, desc.faceIndex );
FontTrueTypePtr ttf =
FontTrueType::New( queryFamily, desc.path, desc.faceIndex, *mResourceScope );
if ( !ttf || !ttf->loaded() ) {
eeSAFE_DELETE( ttf );
mResourceScope->eraseLocalFont( ttf.get() );
return nullptr;
}
return ttf;
};
FontTrueType* boldFont = loadVariant( FontWeight::Bold, false );
FontTrueTypePtr boldFont = loadVariant( FontWeight::Bold, false );
if ( boldFont )
ft->setBoldFont( boldFont );
FontTrueType* italicFont = loadVariant( FontWeight::Normal, true );
FontTrueTypePtr italicFont = loadVariant( FontWeight::Normal, true );
if ( italicFont )
ft->setItalicFont( italicFont );
FontTrueType* boldItalicFont = loadVariant( FontWeight::Bold, true );
FontTrueTypePtr boldItalicFont = loadVariant( FontWeight::Bold, true );
if ( boldItalicFont )
ft->setBoldItalicFont( boldItalicFont );
}
-1
View File
@@ -1,4 +1,3 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/scene/actions/actions.hpp>
#include <eepp/system/functionstring.hpp>
#include <eepp/ui/css/stylesheetpropertyanimation.hpp>
-1
View File
@@ -1,4 +1,3 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/ui/css/propertydefinition.hpp>
+5 -2
View File
@@ -1,8 +1,8 @@
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/ui/css/propertydefinition.hpp>
#include <eepp/ui/uiicon.hpp>
@@ -649,7 +649,10 @@ bool UITextInput::applyProperty( const StyleSheetProperty& attribute ) {
setHintFontSize( lengthFromValue( attribute ) );
break;
case PropertyId::HintFontFamily:
setHintFont( FontManager::instance()->getByName( attribute.value() ) );
setHintFont(
getUISceneNode()
? getUISceneNode()->getResourceScope()->findFont( attribute.value() ).get()
: nullptr );
break;
case PropertyId::HintFontStyle:
setHintFontStyle( attribute.asFontStyle() );
-1
View File
@@ -1,5 +1,4 @@
#include <eepp/core/debug.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/scenemanager.hpp>
#include <eepp/ui/css/propertydefinition.hpp>
-1
View File
@@ -1,5 +1,4 @@
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/actions/actions.hpp>
-1
View File
@@ -1,4 +1,3 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/scene/actions/actions.hpp>
#include <eepp/system/log.hpp>
@@ -2,12 +2,10 @@
#ifdef EE_BACKEND_SDL2
#include <eepp/graphics/framebuffermanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/shaderprogrammanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/vertexbuffermanager.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/log.hpp>
#include <eepp/window/backend/SDL2/clipboardsdl2.hpp>
@@ -2,12 +2,10 @@
#ifdef EE_BACKEND_SDL3
#include <eepp/graphics/framebuffermanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/shaderprogrammanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/vertexbuffermanager.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/log.hpp>
#include <eepp/window/backend/SDL3/clipboardsdl3.hpp>
-3
View File
@@ -1,4 +1,3 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/framebuffermanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
@@ -105,8 +104,6 @@ Engine::~Engine() {
Doc::SyntaxDefinitionManager::destroySingleton();
FontManager::destroySingleton();
Graphics::Private::FrameBufferManager::destroySingleton();
Graphics::Private::VertexBufferManager::destroySingleton();
+8 -7
View File
@@ -25,23 +25,24 @@ EE_MAIN_FUNC int main( int, char*[] ) {
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum." );
FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" );
FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" ).get();
fontTest->loadFromFile( "assets/fonts/DejaVuSansMono.ttf" );
FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" ).get();
fontTest2->loadFromFile( "assets/fonts/NotoSans-Regular.ttf" );
FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" );
FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" ).get();
fontEmoji->loadFromFile( "assets/fonts/NotoEmoji-Regular.ttf" );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" ).get();
fontEmojiColor->loadFromFile( "assets/fonts/NotoColorEmoji.ttf" );
FontBMFont* fontBMFont = FontBMFont::New( "bmfont" );
FontBMFont* fontBMFont = FontBMFont::New( "bmfont" ).get();
fontBMFont->loadFromFile( "assets/fonts/bmfont.fnt" );
FontSprite* fontSprite = FontSprite::New(
"alagard" ); // Alagard - Hewett Tsoi ( https://www.dafont.com/alagard.font )
FontSprite* fontSprite =
FontSprite::New( "alagard" )
.get(); // Alagard - Hewett Tsoi ( https://www.dafont.com/alagard.font )
fontSprite->loadFromFile( "assets/fonts/custom_alagard.png", Color::Fuchsia, 32, -4 );
Text text;
+1 -1
View File
@@ -9,7 +9,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font =
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" ).get();
if ( !font || !font->loaded() )
return EXIT_FAILURE;
@@ -10,10 +10,15 @@ EE_MAIN_FUNC int main( int, char** ) {
return EXIT_FAILURE;
app.getUI()->setThreadPool( threadPool );
ResourceScope& resourceScope = *app.getUI()->getResourceScope();
FontTrueTypePtr remixIconFont =
FontTrueType::New( "icon", "assets/fonts/remixicon.ttf", resourceScope );
FontTrueTypePtr noniconsFont =
FontTrueType::New( "nonicons", "assets/fonts/nonicons.ttf", resourceScope );
FontTrueTypePtr codIconFont =
FontTrueType::New( "codicon", "assets/fonts/codicon.ttf", resourceScope );
app.getUI()->getUIIconThemeManager()->setCurrentTheme(
IconManager::init( "icons", FontTrueType::New( "icon", "assets/fonts/remixicon.ttf" ),
FontTrueType::New( "nonicons", "assets/fonts/nonicons.ttf" ),
FontTrueType::New( "codicon", "assets/fonts/codicon.ttf" ) ) );
IconManager::init( "icons", remixIconFont.get(), noniconsFont.get(), codIconFont.get() ) );
UIFontPickerDialog* dialog = UIFontPickerDialog::New();
dialog->setCloseShortcut( KEY_ESCAPE );
@@ -13,13 +13,12 @@ EE_MAIN_FUNC int main( int, char** ) {
// is always correct even if we load the application from other directory than the binary
// path.
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
// Load a font to use as the default font in our UI.
FontTrueType* font =
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
// Create a new scene node to add our widgets.
UISceneNode* uiSceneNode = UISceneNode::New();
// Load a font to use as the default font in our UI.
FontTrueType* font = FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf",
*uiSceneNode->getResourceScope() )
.get();
// Set the default font used in the scene node (otherwise we won't have any font to create
// text views.
+8 -4
View File
@@ -63,11 +63,15 @@ EE_MAIN_FUNC int main( int argc, char** argv ) {
auto ui = app.getUI();
ui->setThreadPool( threadPool );
FontTrueType* remixIconFont = FontTrueType::New( "icon", "assets/fonts/remixicon.ttf" );
FontTrueType* noniconsFont = FontTrueType::New( "nonicons", "assets/fonts/nonicons.ttf" );
FontTrueType* codIconFont = FontTrueType::New( "codicon", "assets/fonts/codicon.ttf" );
ResourceScope& resourceScope = *ui->getResourceScope();
FontTrueTypePtr remixIconFont =
FontTrueType::New( "icon", "assets/fonts/remixicon.ttf", resourceScope );
FontTrueTypePtr noniconsFont =
FontTrueType::New( "nonicons", "assets/fonts/nonicons.ttf", resourceScope );
FontTrueTypePtr codIconFont =
FontTrueType::New( "codicon", "assets/fonts/codicon.ttf", resourceScope );
ui->getUIIconThemeManager()->setCurrentTheme(
IconManager::init( "icons", remixIconFont, noniconsFont, codIconFont ) );
IconManager::init( "icons", remixIconFont.get(), noniconsFont.get(), codIconFont.get() ) );
ui->setColorSchemePreference(
!prefersColorScheme.Get().empty()
@@ -1,4 +1,4 @@
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontservice.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/text.hpp>
@@ -1391,7 +1391,12 @@ void TerminalDisplay::drawGrid( const Vector2f& pos ) {
auto* gd = mFont->getGlyphDrawable( glyph.u, mFontSize, glyph.mode & ATTR_BOLD,
glyph.mode & ATTR_ITALIC, 0 );
if ( ( glyph.mode & ATTR_EMOJI ) && FontManager::instance()->getColorEmojiFont() ) {
FontService* fontService =
mFont->getType() == FontType::TTF
? static_cast<FontTrueType*>( mFont )->getFontService()
: nullptr;
if ( ( glyph.mode & ATTR_EMOJI ) && fontService &&
fontService->getColorEmojiFont() ) {
gd->setColor( Color::White );
} else {
gd->setColor( fg );
+2 -2
View File
@@ -256,8 +256,8 @@ void EETest::loadFonts() {
}
void EETest::onFontLoaded() {
TTF = FontManager::instance()->getByName( "NotoSans-Regular" );
Font* monospace = FontManager::instance()->getByName( "monospace" );
TTF = defaultResourceScope().findFont( "NotoSans-Regular" ).get();
Font* monospace = defaultResourceScope().findFont( "monospace" ).get();
Log::info( "Fonts loading time: %4.3f ms.", mFTE.getElapsedTimeAndReset().asMilliseconds() );
+5 -5
View File
@@ -168,13 +168,13 @@ int testTextRendering() {
editor->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
editor->setParent( ll );
// editor->setFontSize( PixelDensity::dpToPx( 12 ) );
FontManager::instance()->addFallbackFont(
defaultResourceScope().getFontService().addFallbackFont(
FontTrueType::New( "arabic", "unit_tests/assets/fonts/NotoNaskhArabic-Regular.ttf" ) );
FontManager::instance()->addFallbackFont( FontTrueType::New(
defaultResourceScope().getFontService().addFallbackFont( FontTrueType::New(
"NotoSerifBengali-Regular", "unit_tests/assets/fonts/NotoSansBengali-Regular.ttf" ) );
editor->setWordWrap( true );
// editor->setLineWrapMode( LineWrapMode::Word );
// editor->setFont( FontManager::instance()->getByName( "monospace" ) );
// editor->setFont( defaultResourceScope().findFont( "monospace" ).get() );
// editor->loadFromFile( "unit_tests/assets/textfiles/test-arabic-simple.uext" );
// editor->loadFromFile( "unit_tests/assets/textfiles/test-arabic.uext" );
// editor->loadFromFile( "unit_tests/assets/textfiles/test-bengali.uext" );
@@ -212,8 +212,8 @@ EE_MAIN_FUNC int main( int, char*[] ) {
PixelDensity::setPixelDensity(
Engine::instance()->getDisplayManager()->getDisplayIndex( 0 )->getPixelDensity() );
FontTrueType* font =
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
FontTrueType* iconFont = FontTrueType::New( "icon", "assets/fonts/remixicon.ttf" );
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" ).get();
FontTrueType* iconFont = FontTrueType::New( "icon", "assets/fonts/remixicon.ttf" ).get();
UIIconTheme* iconTheme = UIIconTheme::New( "remixicon" );
auto addIcon = [iconTheme, iconFont]( const std::string& name,
const Uint32& codePoint ) -> UIIcon* {
@@ -25,7 +25,7 @@ using namespace EE::UI::CSS;
static UISceneNode* initDrawableParserTest() {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
@@ -54,7 +54,7 @@ UTEST( DrawableImageParser, TwoStopsWithPosition ) {
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(#f5eedd 0%, #ebe0c2 100%)",
Sizef( 100, 100 ), node );
Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
ASSERT_EQ( drawable->getDrawableType(), Drawable::LINEARGRADIENT );
@@ -82,8 +82,8 @@ UTEST( DrawableImageParser, DirectionToRight ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(to right, red, blue)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "linear-gradient(to right, red, blue)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -105,7 +105,7 @@ UTEST( DrawableImageParser, AngleDegrees ) {
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(45deg, red 0%, blue 100%)",
Sizef( 100, 100 ), node );
Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -124,8 +124,8 @@ UTEST( DrawableImageParser, AngleTurn ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(0.25turn, red, blue)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "linear-gradient(0.25turn, red, blue)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -145,7 +145,7 @@ UTEST( DrawableImageParser, ThreeStops ) {
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(red 0%, green 50%, blue 100%)",
Sizef( 100, 100 ), node );
Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -168,8 +168,8 @@ UTEST( DrawableImageParser, ColorHint ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(red 0%, 25%, blue 100%)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "linear-gradient(red 0%, 25%, blue 100%)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -209,8 +209,8 @@ UTEST( DrawableImageParser, StopsWithoutPositions ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "linear-gradient(red, green, blue)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "linear-gradient(red, green, blue)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -254,8 +254,8 @@ UTEST( DrawableImageParser, RepeatingTwoStops ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "repeating-linear-gradient(red, blue)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "repeating-linear-gradient(red, blue)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
ASSERT_TRUE( drawable->getDrawableType() == Drawable::REPEATINGLINEARGRADIENT );
@@ -301,7 +301,7 @@ UTEST( DrawableImageParser, RepeatingWithPositions ) {
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "repeating-linear-gradient(red 10%, blue 40%)",
Sizef( 100, 100 ), node );
Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<LinearGradientDrawable*>( drawable.get() );
@@ -347,8 +347,8 @@ UTEST( DrawableImageParser, RadialCircleKeyword ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "radial-gradient(circle, #f00, #00f)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "radial-gradient(circle, #f00, #00f)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<RadialGradientDrawable*>( drawable.get() );
@@ -367,8 +367,8 @@ UTEST( DrawableImageParser, RadialWithPositions ) {
UINode* node = createTestNode( sceneNode );
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "radial-gradient(red 10%, blue 80%)",
Sizef( 100, 100 ), node );
DrawablePtr drawable =
parser.createDrawable( "radial-gradient(red 10%, blue 80%)", Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
auto* grad = static_cast<RadialGradientDrawable*>( drawable.get() );
@@ -390,7 +390,7 @@ UTEST( DrawableImageParser, RepeatingRadial ) {
auto& parser = StyleSheetSpecification::instance()->getDrawableImageParser();
DrawablePtr drawable = parser.createDrawable( "repeating-radial-gradient(red 10%, blue 40%)",
Sizef( 100, 100 ), node );
Sizef( 100, 100 ), node );
ASSERT_TRUE( drawable != NULL );
ASSERT_TRUE( drawable->getDrawableType() == Drawable::REPEATINGRADIALGRADIENT );
+148 -50
View File
@@ -4,15 +4,16 @@
#include <eepp/graphics/batchrenderer.hpp>
#include <eepp/graphics/fontbmfont.hpp>
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontsprite.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/image.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/renderer/renderergl.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/richtext.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/scene/scenemanager.hpp>
#include <eepp/system/base64.hpp>
#include <eepp/system/filesystem.hpp>
@@ -35,34 +36,127 @@ using namespace EE::Window;
using namespace EE::UI;
using namespace EE::UI::CSS;
UTEST( FontRendering, relatedFontsDisconnectReplacedCallbacks ) {
FontTrueType* font = FontTrueType::New( "RelatedFontsDisconnect-Regular" );
FontTrueType* oldBold = FontTrueType::New( "RelatedFontsDisconnect-OldBold" );
FontTrueType* newBold = FontTrueType::New( "RelatedFontsDisconnect-NewBold" );
FontTrueType* oldItalic = FontTrueType::New( "RelatedFontsDisconnect-OldItalic" );
FontTrueType* newItalic = FontTrueType::New( "RelatedFontsDisconnect-NewItalic" );
FontTrueType* oldBoldItalic = FontTrueType::New( "RelatedFontsDisconnect-OldBoldItalic" );
FontTrueType* newBoldItalic = FontTrueType::New( "RelatedFontsDisconnect-NewBoldItalic" );
UTEST( FontRendering, drawingEmptyTextDoesNotCreateFontPage ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - Empty Text Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
font->setBoldFont( oldBold );
font->setBoldFont( newBold );
eeDelete( oldBold );
EXPECT_EQ( newBold, font->getBoldFont() );
FontDesc desc;
desc.family = "Empty Text Test";
desc.path = Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
FontTrueTypePtr font = app.getUI()->getResourceScope()->getFontService().loadSystemFont( desc );
ASSERT_TRUE( font );
font->setItalicFont( oldItalic );
font->setItalicFont( newItalic );
eeDelete( oldItalic );
EXPECT_EQ( newItalic, font->getItalicFont() );
TextureFactory* textureFactory = TextureFactory::instance();
const Uint32 textureCount = textureFactory->getTextureCount();
Text::draw( String{}, Vector2f::Zero, font.get(), 10, Color::White );
font->setBoldItalicFont( oldBoldItalic );
font->setBoldItalicFont( newBoldItalic );
eeDelete( oldBoldItalic );
EXPECT_EQ( newBoldItalic, font->getBoldItalicFont() );
EXPECT_EQ( textureCount, textureFactory->getTextureCount() );
}
eeDelete( font );
eeDelete( newBold );
eeDelete( newItalic );
eeDelete( newBoldItalic );
UTEST( FontRendering, glyphAdvanceDoesNotCreateTexturePages ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - Glyph Advance Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
ResourceScope& scope = *app.getUI()->getResourceScope();
FontTrueTypePtr font = FontTrueType::New( "GlyphAdvance-Regular", scope );
ASSERT_TRUE(
font->loadFromFile( Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf" ) );
TextureFactory* textureFactory = TextureFactory::instance();
const Uint32 textureCount = textureFactory->getTextureCount();
const Float advance = font->getGlyphAdvance( ' ', 10 );
const Float outlinedAdvance = font->getGlyphAdvance( ' ', 10, false, false, 2.f );
EXPECT_TRUE( advance > 0 );
EXPECT_EQ( advance, outlinedAdvance );
EXPECT_EQ( textureCount, textureFactory->getTextureCount() );
}
UTEST( FontRendering, loadingFontFamilyDoesNotCreateTexturePages ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - Font Family Metrics Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
ResourceScope& scope = *app.getUI()->getResourceScope();
FontTrueTypePtr font = FontTrueType::New( "FontFamilyMetrics-Regular", scope );
ASSERT_TRUE(
font->loadFromFile( Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf" ) );
TextureFactory* textureFactory = TextureFactory::instance();
const Uint32 textureCount = textureFactory->getTextureCount();
FontFamily::loadFromRegular( font.get() );
EXPECT_TRUE( font->hasBold() );
EXPECT_TRUE( font->hasItalic() );
EXPECT_EQ( textureCount, textureFactory->getTextureCount() );
}
UTEST( FontRendering, regularFontOwnsRelatedFonts ) {
FontTrueTypePtr font = FontTrueType::New( "RelatedFonts-Regular" );
FontTrueTypePtr bold = FontTrueType::New( "RelatedFonts-Bold" );
FontTrueTypePtr italic = FontTrueType::New( "RelatedFonts-Italic" );
FontTrueTypePtr boldItalic = FontTrueType::New( "RelatedFonts-BoldItalic" );
FontTrueTypeWeakPtr weakBold = bold;
FontTrueTypeWeakPtr weakItalic = italic;
FontTrueTypeWeakPtr weakBoldItalic = boldItalic;
font->setBoldFont( bold );
font->setItalicFont( italic );
font->setBoldItalicFont( boldItalic );
defaultResourceScope().eraseLocalFont( bold.get() );
defaultResourceScope().eraseLocalFont( italic.get() );
defaultResourceScope().eraseLocalFont( boldItalic.get() );
bold.reset();
italic.reset();
boldItalic.reset();
EXPECT_TRUE( font->getBoldFont() );
EXPECT_TRUE( font->getItalicFont() );
EXPECT_TRUE( font->getBoldItalicFont() );
EXPECT_FALSE( weakBold.expired() );
EXPECT_FALSE( weakItalic.expired() );
EXPECT_FALSE( weakBoldItalic.expired() );
defaultResourceScope().eraseLocalFont( font.get() );
font.reset();
EXPECT_TRUE( weakBold.expired() );
EXPECT_TRUE( weakItalic.expired() );
EXPECT_TRUE( weakBoldItalic.expired() );
}
UTEST( FontRendering, destroyingFontInvalidatesTextLayoutCache ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - Text Layout Cache Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
ResourceScope& scope = *app.getUI()->getResourceScope();
FontTrueTypePtr font = FontTrueType::New( "TextLayoutCache-Regular", scope );
FontTrueTypePtr retainedFont = FontTrueType::New( "TextLayoutCache-Retained", scope );
ASSERT_TRUE(
font->loadFromFile( Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf" ) );
ASSERT_TRUE( retainedFont->loadFromFile( Sys::getProcessPath() +
"../assets/fonts/NotoSans-Regular.ttf" ) );
TextLayout::Cache layout =
TextLayout::layout( String( "cached shaped text" ), font.get(), 14, Text::Regular );
TextLayout::Cache retainedLayout = TextLayout::layout( String( "unrelated cached text" ),
retainedFont.get(), 14, Text::Regular );
std::weak_ptr<const TextLayout> layoutWeak = layout;
std::weak_ptr<const TextLayout> retainedLayoutWeak = retainedLayout;
layout.reset();
retainedLayout.reset();
EXPECT_FALSE( layoutWeak.expired() );
EXPECT_FALSE( retainedLayoutWeak.expired() );
EXPECT_TRUE( scope.eraseLocalFont( font.get() ) );
font.reset();
EXPECT_TRUE( layoutWeak.expired() );
EXPECT_FALSE( retainedLayoutWeak.expired() );
}
UTEST( FontRendering, fontsTest ) {
@@ -85,22 +179,22 @@ UTEST( FontRendering, fontsTest ) {
"cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "
"proident, sunt in culpa qui officia deserunt mollit anim id est laborum." );
FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" );
FontTrueType* fontTest = FontTrueType::New( "DejaVuSansMono" ).get();
fontTest->loadFromFile( "../assets/fonts/DejaVuSansMono.ttf" );
FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* fontTest2 = FontTrueType::New( "NotoSans-Regular" ).get();
fontTest2->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" );
FontTrueType* fontEmoji = FontTrueType::New( "NotoEmoji-Regular" ).get();
fontEmoji->loadFromFile( "../assets/fonts/NotoEmoji-Regular.ttf" );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" ).get();
fontEmojiColor->loadFromFile( "../assets/fonts/NotoColorEmoji.ttf" );
FontBMFont* fontBMFont = FontBMFont::New( "bmfont" );
FontBMFont* fontBMFont = FontBMFont::New( "bmfont" ).get();
fontBMFont->loadFromFile( "../assets/fonts/bmfont.fnt" );
FontSprite* fontSprite = FontSprite::New( "alagard" );
FontSprite* fontSprite = FontSprite::New( "alagard" ).get();
fontSprite->loadFromFile( "../assets/fonts/custom_alagard.png", Color::Fuchsia, 32, -4 );
Text text;
@@ -288,7 +382,7 @@ UTEST( FontRendering, loadFontFaceDataURI ) {
SceneManager::instance()->add( sceneNode );
UI::UIThemeManager* themeManager = sceneNode->getUIThemeManager();
FontTrueType* baseFont = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* baseFont = FontTrueType::New( "NotoSans-Regular" ).get();
baseFont->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
themeManager->setDefaultFont( baseFont );
@@ -315,7 +409,7 @@ UTEST( FontRendering, loadFontFaceDataURI ) {
Font* loadedFont = sceneNode->getFontFromNamesList( "DataURIFont" );
ASSERT_NE( loadedFont, nullptr );
ASSERT_TRUE_MSG( loadedFont->loaded(), "Font loaded via data URI is not loaded" );
EXPECT_EQ( nullptr, FontManager::instance()->getByName( "DataURIFont" ) );
EXPECT_EQ( nullptr, defaultResourceScope().findFont( "DataURIFont" ).get() );
Engine::destroySingleton();
}
@@ -353,7 +447,7 @@ UTEST( FontRendering, fontFaceAuthorFamilyIsSceneScoped ) {
EXPECT_TRUE( fontB->loaded() );
EXPECT_NE( fontA, fontB );
EXPECT_TRUE( fontA->getName() != fontB->getName() );
EXPECT_EQ( nullptr, FontManager::instance()->getByName( "ScopedAuthorFace" ) );
EXPECT_EQ( nullptr, defaultResourceScope().findFont( "ScopedAuthorFace" ).get() );
Engine::destroySingleton();
}
@@ -631,8 +725,9 @@ UTEST( FontRendering, textEditBengaliTest ) {
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1.5f ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* bengaliFont =
FontTrueType::New( "NotoSansBengali-Regular", "assets/fonts/NotoSansBengali-Regular.ttf" );
FontManager::instance()->addFallbackFont( bengaliFont );
FontTrueType::New( "NotoSansBengali-Regular", "assets/fonts/NotoSansBengali-Regular.ttf" )
.get();
defaultResourceScope().getFontService().addFallbackFont( bengaliFont );
UTEST_PRINT_STEP( "Text Shaper enabled" );
auto* editor = UITextEdit::New();
// editor->setFontSize( PixelDensity::dpToPx( 12 ) );
@@ -651,8 +746,9 @@ UTEST( FontRendering, textEditArabicTest ) {
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1.5f ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* arabicFont =
FontTrueType::New( "NotoNaskhArabic-Regular", "assets/fonts/NotoNaskhArabic-Regular.ttf" );
FontManager::instance()->addFallbackFont( arabicFont );
FontTrueType::New( "NotoNaskhArabic-Regular", "assets/fonts/NotoNaskhArabic-Regular.ttf" )
.get();
defaultResourceScope().getFontService().addFallbackFont( arabicFont );
UTEST_PRINT_STEP( "Text Shaper enabled" );
auto* editor = UITextEdit::New();
// editor->setFontSize( PixelDensity::dpToPx( 12 ) );
@@ -671,8 +767,9 @@ UTEST( FontRendering, textEditHebrewTest ) {
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1.5f ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* hebrewFont =
FontTrueType::New( "NotoSansHebrew-Regular", "assets/fonts/NotoSansHebrew-Regular.ttf" );
FontManager::instance()->addFallbackFont( hebrewFont );
FontTrueType::New( "NotoSansHebrew-Regular", "assets/fonts/NotoSansHebrew-Regular.ttf" )
.get();
defaultResourceScope().getFontService().addFallbackFont( hebrewFont );
UTEST_PRINT_STEP( "Text Shaper enabled" );
auto* editor = UITextEdit::New();
// editor->setFontSize( PixelDensity::dpToPx( 12 ) );
@@ -692,7 +789,7 @@ UTEST( FontRendering, textSizes ) {
Text::TextShaperEnabled = false;
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontStyleConfig config;
@@ -793,7 +890,7 @@ UTEST( FontRendering, textStyles ) {
Text::TextShaperEnabled = false;
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
@@ -876,11 +973,11 @@ UTEST( FontRendering, emojisWithText ) {
Text::TextShaperEnabled = false;
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" );
FontTrueType* fontEmojiColor = FontTrueType::New( "NotoColorEmoji" ).get();
fontEmojiColor->loadFromFile( "../assets/fonts/NotoColorEmoji.ttf" );
win->setClearColor( RGB( 255, 255, 255 ) );
@@ -934,7 +1031,8 @@ UTEST( FontRendering, textSetFillColor ) {
win->setClearColor( RGB( 230, 230, 230 ) );
FontTrueType* arabicFont =
FontTrueType::New( "NotoNaskhArabic-Regular", "assets/fonts/NotoNaskhArabic-Regular.ttf" );
FontTrueType::New( "NotoNaskhArabic-Regular", "assets/fonts/NotoNaskhArabic-Regular.ttf" )
.get();
Text text;
text.setFont( arabicFont );
@@ -1364,7 +1462,7 @@ UTEST( FontRendering, TextSoftWrapPos ) {
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "DejaVuSansMono" );
FontTrueType* font = FontTrueType::New( "DejaVuSansMono" ).get();
font->loadFromFile( "../assets/fonts/DejaVuSansMono.ttf" );
Text text;
@@ -1414,7 +1512,7 @@ UTEST( FontRendering, TextSelection ) {
Text::TextShaperEnabled = false;
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
bool loaded = font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( loaded );
FontFamily::loadFromRegular( font );
@@ -1501,7 +1599,7 @@ UTEST( FontRendering, TextInitialOffset ) {
win->setClearColor( RGB( 255, 255, 255 ) );
win->clear();
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
Primitives p;
@@ -1568,7 +1666,7 @@ UTEST( FontRendering, TextContiguousOffset ) {
win->setClearColor( RGB( 255, 255, 255 ) );
win->clear();
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
Float maxWidth = 450.f;
@@ -1681,7 +1779,7 @@ UTEST( FontRendering, TextBackgroundColor ) {
win->setClearColor( RGB( 255, 255, 255 ) );
win->clear();
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
Vector2f pos{ 20, 20 };
+1 -1
View File
@@ -26,7 +26,7 @@ static UISceneNode* createScene() {
true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
if ( !font->loaded() ) {
Engine::destroySingleton();
@@ -5,7 +5,8 @@
#include <condition_variable>
#include <eepp/core/lrucache.hpp>
#include <eepp/graphics/drawablegroup.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fontbmfont.hpp>
#include <eepp/graphics/fontsprite.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/framebuffermanager.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
@@ -199,6 +200,18 @@ EE::Window::Window* createLifecycleTestWindow( const std::string& title ) {
static_assert( !std::is_copy_constructible<Texture>::value, "Texture must not be copyable" );
static_assert( !std::is_copy_assignable<Texture>::value, "Texture must not be copy-assignable" );
static_assert( std::is_invocable_r_v<std::size_t, std::hash<ResourceId>, const ResourceId&>,
"ResourceId must support standard unordered containers" );
UTEST( ResourcePrerequisites, resourceIdSupportsUnorderedContainers ) {
UnorderedMap<ResourceId, int> resources;
resources[ResourceId( 1 )] = 10;
resources[ResourceId( 2 )] = 20;
EXPECT_EQ( 10, resources[ResourceId( 1 )] );
EXPECT_EQ( 20, resources[ResourceId( 2 )] );
EXPECT_EQ( (size_t)2, resources.size() );
}
UTEST( ResourcePrerequisites, lruCacheEvictsOnlyLeastRecentlyUsedAndReleasesKeys ) {
LRUCache<2, int, bool> recencyCache;
@@ -221,6 +234,21 @@ UTEST( ResourcePrerequisites, lruCacheEvictsOnlyLeastRecentlyUsedAndReleasesKeys
owningKeyCache.clear();
EXPECT_TRUE( weakKey.expired() );
LRUCache<3, int, int> selectiveCache;
selectiveCache.put( 1, 10 );
selectiveCache.put( 2, 20 );
selectiveCache.put( 3, 30 );
ASSERT_TRUE( selectiveCache.get( 1 ).has_value() );
selectiveCache.eraseIf( []( int key, int ) { return key == 2; } );
EXPECT_TRUE( !selectiveCache.get( 2 ).has_value() );
EXPECT_EQ( (size_t)2, selectiveCache.size() );
selectiveCache.put( 4, 40 );
selectiveCache.put( 5, 50 );
EXPECT_TRUE( !selectiveCache.get( 3 ).has_value() );
EXPECT_TRUE( selectiveCache.get( 1 ).has_value() );
EXPECT_TRUE( selectiveCache.get( 4 ).has_value() );
EXPECT_TRUE( selectiveCache.get( 5 ).has_value() );
}
UTEST( ResourcePrerequisites, textureAtlasLoaderAppliesFilterToEveryTexture ) {
@@ -495,6 +523,92 @@ UTEST( ResourcePrerequisites, defaultResourceScopeImportsGlobalCatalog ) {
Engine::destroySingleton();
}
UTEST( ResourcePrerequisites, uiScenesImportDefaultResourcesUnlessDisabled ) {
EE::Window::Window* window = createLifecycleTestWindow( "UI scene default resources test" );
TexturePtr texture = TextureFactory::instance()->createEmptyTexture( 1, 1 );
ASSERT_TRUE( texture != nullptr );
defaultResourceScope().publishLocal( "ui-scene-default-texture", texture );
UISceneNode* defaultScene = UISceneNode::New( window );
UISceneNode* isolatedScene = UISceneNode::New( window, false );
EXPECT_EQ( texture.get(),
defaultScene->getResourceScope()->findTexture( "ui-scene-default-texture" ).get() );
EXPECT_TRUE( isolatedScene->getResourceScope()->findTexture( "ui-scene-default-texture" ) ==
nullptr );
defaultScene->setResourceScope( ResourceScope::New() );
EXPECT_EQ( texture.get(),
defaultScene->getResourceScope()->findTexture( "ui-scene-default-texture" ).get() );
eeDelete( isolatedScene );
eeDelete( defaultScene );
defaultResourceScope().eraseLocal( "ui-scene-default-texture" );
texture.reset();
window->display( false );
Engine::destroySingleton();
}
UTEST( ResourcePrerequisites, fontServiceFollowsScopeOwnershipAndDetachesRetainedFonts ) {
EE::Window::Window* window = createLifecycleTestWindow( "Font service scope test" );
ResourceScopePtr scope = ResourceScope::New();
FontTrueTypePtr font = FontTrueType::New( "scoped-font-service", *scope );
ASSERT_TRUE( font != nullptr );
EXPECT_EQ( &scope->getFontService(), font->getFontService() );
EXPECT_EQ( font.get(), scope->findFont( "scoped-font-service" ).get() );
EXPECT_TRUE( scope->getFontService().addFallbackFont( font ) );
EXPECT_TRUE( scope->getFontService().hasFallbackFonts() );
EXPECT_TRUE( scope->eraseLocalFont( font.get() ) );
EXPECT_EQ( nullptr, font->getFontService() );
EXPECT_FALSE( scope->getFontService().hasFallbackFonts() );
EXPECT_TRUE( scope->findFont( "scoped-font-service" ) == nullptr );
font.reset();
scope.reset();
window->display( false );
Engine::destroySingleton();
}
UTEST( ResourcePrerequisites, fontFactoriesPublishIntoExplicitScope ) {
EE::Window::Window* window = createLifecycleTestWindow( "Scoped font factories test" );
auto scope = ResourceScope::New();
auto bmFont = FontBMFont::New( "scoped-bm-font", *scope );
auto spriteFont = FontSprite::New( "scoped-sprite-font", *scope );
EXPECT_EQ( bmFont.get(), scope->findFont( "scoped-bm-font" ).get() );
EXPECT_EQ( spriteFont.get(), scope->findFont( "scoped-sprite-font" ).get() );
EXPECT_EQ( nullptr, defaultResourceScope().findFont( "scoped-bm-font" ).get() );
EXPECT_EQ( nullptr, defaultResourceScope().findFont( "scoped-sprite-font" ).get() );
bmFont.reset();
spriteFont.reset();
scope.reset();
window->display( false );
Engine::destroySingleton();
}
UTEST( ResourcePrerequisites, duplicateFontNamesReplaceCatalogBinding ) {
EE::Window::Window* window = createLifecycleTestWindow( "Font replacement semantics test" );
auto scope = ResourceScope::New();
FontTrueTypePtr first = FontTrueType::New( "replaceable-font", *scope );
FontTrueTypePtr second = FontTrueType::New( "replaceable-font", *scope );
FontTrueTypeWeakPtr firstWeak = first;
EXPECT_STRINGEQ( "replaceable-font", first->getName() );
EXPECT_STRINGEQ( "replaceable-font", second->getName() );
EXPECT_EQ( second.get(), scope->findFont( "replaceable-font" ).get() );
EXPECT_EQ( nullptr, first->getFontService() );
EXPECT_EQ( &scope->getFontService(), second->getFontService() );
first.reset();
EXPECT_TRUE( firstWeak.expired() );
second.reset();
scope.reset();
window->display( false );
Engine::destroySingleton();
}
UTEST( ResourcePrerequisites, uiScenesOwnIsolatedScopesThatCanBeSharedExplicitly ) {
EE::Window::Window* window = createLifecycleTestWindow( "UI scene resource scope test" );
UISceneNode* firstScene = UISceneNode::New( window );
@@ -1049,10 +1163,11 @@ UTEST( ResourcePrerequisites, engineTeardownReleasesGraphicsBeforeContextsAcross
scene->enableFrameBuffer();
UIImage::New()->setDrawable( ninePatch->clone() )->setParent( scene->getRoot() );
auto* font = FontTrueType::New( "engine-teardown-font" );
FontTrueTypePtr font = FontTrueType::New( "engine-teardown-font" );
ASSERT_TRUE(
font->loadFromFile( Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf" ) );
auto layout = TextLayout::layout( String( "cached before Engine teardown" ), font, 14, 0 );
auto layout =
TextLayout::layout( String( "cached before Engine teardown" ), font.get(), 14, 0 );
std::weak_ptr<const TextLayout> layoutWeak = layout;
layout.reset();
@@ -1061,6 +1176,7 @@ UTEST( ResourcePrerequisites, engineTeardownReleasesGraphicsBeforeContextsAcross
batch->batchQuad( 0, 0, 4, 4 );
ninePatch.reset();
texture.reset();
font.reset();
Engine::destroySingleton();
@@ -1068,7 +1184,6 @@ UTEST( ResourcePrerequisites, engineTeardownReleasesGraphicsBeforeContextsAcross
EXPECT_TRUE( Engine::existsSingleton() == nullptr );
EXPECT_TRUE( SceneManager::existsSingleton() == nullptr );
EXPECT_TRUE( GlobalBatchRenderer::existsSingleton() == nullptr );
EXPECT_TRUE( FontManager::existsSingleton() == nullptr );
EXPECT_TRUE( TextureFactory::existsSingleton() == nullptr );
EXPECT_TRUE( ShaderProgramManager::existsSingleton() == nullptr );
EXPECT_TRUE( Graphics::Private::FrameBufferManager::existsSingleton() == nullptr );
+17 -19
View File
@@ -40,7 +40,7 @@ static UISceneNode* createRichTextScene() {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
if ( !font->loaded() ) {
Engine::destroySingleton();
@@ -94,7 +94,7 @@ UTEST( RichText, basicFunctionality ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -141,7 +141,7 @@ UTEST( RichText, selection ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -222,7 +222,7 @@ UTEST( RichText, BaselineAlignment ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -260,7 +260,7 @@ UTEST( RichText, VerticalAlignAtomicBoxes ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -355,7 +355,7 @@ UTEST( RichText, InlineTextUsesActiveInlineBoxAlignment ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -403,7 +403,7 @@ UTEST( RichText, InlineAncestorLineHeightContributesToLineHeight ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -452,7 +452,7 @@ UTEST( RichText, FloatAwareInlineLayoutUsesTreeOrder ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -487,7 +487,7 @@ UTEST( RichText, RenderSpanPayloadSupportsDrawableAndAtomicSelection ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -545,7 +545,7 @@ UTEST( RichText, InlineBoxHorizontalEdgesContributeToAdvance ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -607,7 +607,7 @@ UTEST( RichText, HitTestingSnapsAcrossInlineBoxSpacing ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -653,7 +653,7 @@ UTEST( RichText, SelectionRectsUseInlineFragments ) {
WindowBackend::Default, 32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -699,7 +699,7 @@ UTEST( RichText, InlineParentTextDecorationReachesFragments ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -748,7 +748,7 @@ UTEST( RichText, AtomicInlineBoxBaselineAlignment ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -778,7 +778,7 @@ UTEST( LineWrap, SoftWrapPreventsWordSplitWithOffset ) {
WindowStyle::Default, WindowBackend::Default,
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
@@ -798,8 +798,6 @@ UTEST( LineWrap, SoftWrapPreventsWordSplitWithOffset ) {
ASSERT_GE( info.wraps.size(), (size_t)2 );
EXPECT_EQ( info.wraps[1], 1 );
delete font;
Engine::destroySingleton();
}
@@ -840,7 +838,7 @@ UTEST( RichText, RichTextTest ) {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font =
FontTrueType::New( "NotoSans-Regular", "../assets/fonts/NotoSans-Regular.ttf" );
FontTrueType::New( "NotoSans-Regular", "../assets/fonts/NotoSans-Regular.ttf" ).get();
ASSERT_TRUE( font && font->loaded() );
@@ -1738,7 +1736,7 @@ UTEST( RichText, BreakSpacesWrapsAfterPreservedSpacesAndTabs ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1,7 +1,7 @@
#include "utest.hpp"
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/sys.hpp>
@@ -548,12 +548,12 @@ UTEST( FontTrueType_faceIndex, loadWithDefaultFaceIndex ) {
std::string fontPath = getFontsDir() + "DejaVuSansMono.ttf";
ASSERT_TRUE( FileSystem::fileExists( fontPath ) );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-default" );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-default" ).get();
bool loaded = font->loadFromFile( fontPath );
ASSERT_TRUE( loaded );
EXPECT_TRUE( font->loaded() );
eeDelete( font );
defaultResourceScope().eraseLocalFont( font );
}
UTEST( FontTrueType_faceIndex, newWithFaceIndex ) {
@@ -562,11 +562,11 @@ UTEST( FontTrueType_faceIndex, newWithFaceIndex ) {
std::string fontPath = getFontsDir() + "DejaVuSansMono.ttf";
ASSERT_TRUE( FileSystem::fileExists( fontPath ) );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-explicit", fontPath, 0 );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-explicit", fontPath, 0 ).get();
ASSERT_TRUE( font != nullptr );
EXPECT_TRUE( font->loaded() );
eeDelete( font );
defaultResourceScope().eraseLocalFont( font );
}
UTEST( FontTrueType_faceIndex, loadFromMemoryFaceIndex ) {
@@ -578,10 +578,10 @@ UTEST( FontTrueType_faceIndex, loadFromMemoryFaceIndex ) {
ScopedBuffer buf;
FileSystem::fileGet( fontPath, buf );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-memory" );
FontTrueType* font = FontTrueType::New( "Test-faceIndex-memory" ).get();
bool loaded = font->loadFromMemory( buf.get(), buf.length(), true, 0 );
ASSERT_TRUE( loaded );
EXPECT_TRUE( font->loaded() );
eeDelete( font );
defaultResourceScope().eraseLocalFont( font );
}
@@ -1,7 +1,7 @@
#include "utest.hpp"
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/pixeldensity.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/scene/node.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/ui/css/stylesheet.hpp>
@@ -1,7 +1,9 @@
#include "utest.hpp"
#include <algorithm>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/systemfontresolver.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/threadpool.hpp>
#include <eepp/ui/abstract/uiabstractview.hpp>
@@ -47,6 +49,16 @@ template <typename Predicate> static void pumpUntil( UISceneNode* sceneNode, Pre
}
}
class TestFontPickerDialog : public UIFontPickerDialog {
public:
static TestFontPickerDialog* New() { return eeNew( TestFontPickerDialog, () ); }
FontTrueTypeWeakPtr getPreviewFontHandle() const { return mPreviewFont; }
protected:
TestFontPickerDialog() : UIFontPickerDialog() {}
};
UTEST( UIFontPickerDialog, PreselectsExternalFontPath ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
@@ -55,7 +67,6 @@ UTEST( UIFontPickerDialog, PreselectsExternalFontPath ) {
const std::string fontPath = Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
ASSERT_TRUE( FileSystem::fileExists( fontPath ) );
UIFontPickerDialog* dialog = UIFontPickerDialog::New();
dialog->setSelectedFont( fontPath );
@@ -73,6 +84,150 @@ UTEST( UIFontPickerDialog, PreselectsExternalFontPath ) {
EXPECT_FALSE( selectionDialog->getSelection().font.family.empty() );
}
UTEST( UIFontPickerDialog, PreviewFontsDoNotPopulateSceneFontCatalog ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
const std::string koreanFontPath =
Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
const std::string hebrewFontPath =
Sys::getProcessPath() + "assets/fonts/NotoSansHebrew-Regular.ttf";
ASSERT_TRUE( FileSystem::fileExists( koreanFontPath ) );
ASSERT_TRUE( FileSystem::fileExists( hebrewFontPath ) );
UIFontPickerDialog* dialog = UIFontPickerDialog::New();
ResourceScope& sceneScope = *app.getUI()->getResourceScope();
const size_t sceneFontCount = sceneScope.getFonts().size();
dialog->setSelectedFont( koreanFontPath );
dialog->setSelectedFont( hebrewFontPath );
EXPECT_EQ( sceneFontCount, sceneScope.getFonts().size() );
}
UTEST( UIFontPickerDialog, SelectingFontDoesNotCreateMetricOnlyPage ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
const std::string fontPath = Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
ASSERT_TRUE( FileSystem::fileExists( fontPath ) );
UIFontPickerDialog* dialog = UIFontPickerDialog::New();
dialog->setSelectedFont( fontPath );
app.getUI()->draw();
GlobalBatchRenderer::instance()->draw();
bool foundPreviewPage = false;
for ( const auto& texture : TextureFactory::instance()->snapshotTextures() ) {
if ( String::startsWith( texture.displayName, "@font:TrueType:Noto Sans KR:" ) ) {
foundPreviewPage = true;
EXPECT_FALSE( String::endsWith( texture.displayName, ":10" ) );
}
}
EXPECT_TRUE( foundPreviewPage );
}
UTEST( UIFontPickerDialog, ReleasesPreviewFontTexturesOnClose ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
const std::string koreanFontPath =
Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
const std::string hebrewFontPath =
Sys::getProcessPath() + "assets/fonts/NotoSansHebrew-Regular.ttf";
ASSERT_TRUE( FileSystem::fileExists( koreanFontPath ) );
ASSERT_TRUE( FileSystem::fileExists( hebrewFontPath ) );
TextureFactory* textureFactory = TextureFactory::instance();
UnorderedSet<ResourceId> baselineIds;
for ( const auto& texture : textureFactory->snapshotTextures() )
baselineIds.insert( texture.id );
UIFontPickerDialog* dialog = UIFontPickerDialog::New();
dialog->setSelectedFont( koreanFontPath );
app.getUI()->draw();
dialog->setSelectedFont( hebrewFontPath );
app.getUI()->draw();
GlobalBatchRenderer::instance()->draw();
std::vector<std::pair<std::string, TextureWeakPtr>> previewTextures;
for ( const auto& texture : textureFactory->snapshotTextures() ) {
if ( baselineIds.find( texture.id ) == baselineIds.end() &&
( String::contains( texture.displayName, "Noto Sans KR" ) ||
String::contains( texture.displayName, "Noto Sans Hebrew" ) ) )
previewTextures.emplace_back( texture.displayName, texture.texture );
}
ASSERT_FALSE( previewTextures.empty() );
dialog->close();
app.getUI()->update( Time::Zero );
GlobalBatchRenderer::instance()->draw();
textureFactory->collectReleasedTextures();
for ( const auto& texture : previewTextures )
EXPECT_TRUE( texture.second.expired() );
}
UTEST( UIFontPickerDialog, ReleasesEnumeratedSystemFontTexturesOnClose ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), 1 ) );
app.getUI()->getResourceScope()->clearImports();
std::vector<FontDesc> systemFonts;
UnorderedSet<std::string> families;
for ( const FontDesc& font : SystemFontResolver::instance()->enumerate() ) {
if ( font.path.empty() || font.family.empty() || !families.insert( font.family ).second )
continue;
systemFonts.emplace_back( font );
if ( systemFonts.size() == 3 )
break;
}
if ( systemFonts.size() < 2 )
UTEST_SKIP( "fewer than two distinct system font families available" );
TextureFactory* textureFactory = TextureFactory::instance();
TestFontPickerDialog* dialog = TestFontPickerDialog::New();
app.getUI()->draw();
GlobalBatchRenderer::instance()->draw();
std::vector<FontTrueTypeWeakPtr> previewFonts;
std::vector<TextureWeakPtr> previewTextures;
for ( const FontDesc& font : systemFonts ) {
dialog->setSelectedFont( font );
app.getUI()->draw();
GlobalBatchRenderer::instance()->draw();
FontTrueTypePtr previewFont = dialog->getPreviewFontHandle().lock();
ASSERT_TRUE( previewFont );
previewFonts.emplace_back( previewFont );
previewTextures.emplace_back(
previewFont->getTexture( PixelDensity::dpToPxI( dialog->getSelection().size * 2 ) ) );
previewTextures.emplace_back( previewFont->getTexture( PixelDensity::dpToPxI( 12 ) ) );
}
dialog->close();
GlobalBatchRenderer::instance()->draw();
pumpUntil( app.getUI(), [&] {
textureFactory->collectReleasedTextures();
textureFactory->purgeExpiredTextures();
return std::all_of( previewFonts.begin(), previewFonts.end(),
[]( const FontTrueTypeWeakPtr& font ) { return font.expired(); } ) &&
std::all_of( previewTextures.begin(), previewTextures.end(),
[]( const TextureWeakPtr& texture ) { return texture.expired(); } );
} );
for ( const auto& font : previewFonts )
EXPECT_TRUE( font.expired() );
for ( const auto& texture : previewTextures )
EXPECT_TRUE( texture.expired() );
}
UTEST( UIFontPickerDialog, AsyncLoadPreservesExternalFontPreselection ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
@@ -108,7 +263,7 @@ UTEST( UIFontPickerDialog, DefaultColorComesFromTheme ) {
EXPECT_TRUE( dialog->getSelection().color.a != 0 );
}
UTEST( UIFontPickerDialog, IncludesDiskFontsLoadedInFontManager ) {
UTEST( UIFontPickerDialog, IncludesDiskFontsLoadedInDefaultScope ) {
UIApplication app(
WindowSettings( 320, 240, "eepp - UIFontPickerDialog Test", WindowStyle::Default,
WindowBackend::Default, 32 ),
@@ -117,7 +272,9 @@ UTEST( UIFontPickerDialog, IncludesDiskFontsLoadedInFontManager ) {
const std::string fontPath = Sys::getProcessPath() + "assets/fonts/NotoSansKR-Regular.ttf";
ASSERT_TRUE( FileSystem::fileExists( fontPath ) );
FontTrueType* font = FontTrueType::New( "UIFontPickerDialogManagedNotoSansKR", fontPath );
FontTrueTypePtr fontHandle =
FontTrueType::New( "UIFontPickerDialogManagedNotoSansKR", fontPath );
FontTrueType* font = fontHandle.get();
ASSERT_TRUE( font != nullptr );
ASSERT_TRUE( font->loaded() );
ASSERT_FALSE( font->getInfo().family.empty() );
+1 -1
View File
@@ -24,7 +24,7 @@ using namespace EE::Graphics;
static void init_flex_test() {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
UISceneNode* sceneNode = UISceneNode::New();
+2 -2
View File
@@ -26,7 +26,7 @@ static void init_float_test() {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
@@ -1161,7 +1161,7 @@ UTEST( UIHTMLFloat, floatNotAffectedByTextAlignCenter ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
+1 -1
View File
@@ -26,7 +26,7 @@ using namespace EE::Graphics;
static void init_grid_test() {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
UISceneNode* sceneNode = UISceneNode::New();
@@ -25,7 +25,7 @@ static void init_ui_test() {
WindowBackend::Default, 32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
+28 -29
View File
@@ -2,10 +2,10 @@
#include "utest.hpp"
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/image.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/texturedrawable.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/textureregion.hpp>
@@ -80,10 +80,10 @@ static void init_ui_test() {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
FontTrueType* monospace = FontTrueType::New( "monospace" );
FontTrueType* monospace = FontTrueType::New( "monospace" ).get();
monospace->loadFromFile( "../assets/fonts/DejaVuSansMono.ttf" );
FontFamily::loadFromRegular( monospace );
@@ -131,7 +131,7 @@ UTEST( UIHTMLTable, complexLayout ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -192,7 +192,7 @@ UTEST( UIHTMLTable, complexLayout2 ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -251,7 +251,7 @@ UTEST( UIHTML, redditOldThreadWebViewSmoke ) {
UTEST_SKIP( "old Reddit fixture CSS asset is not readable" );
}
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1048,7 +1048,7 @@ UTEST( UIRichText, anchorMargins ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1090,7 +1090,7 @@ UTEST( UIRichText, spanPadding ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1124,7 +1124,7 @@ UTEST( UIRichText, anchorPadding ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1164,7 +1164,7 @@ UTEST( UIRichText, anchorPaddingLineHeight ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1204,7 +1204,7 @@ UTEST( UIHTML, InlineBaselineAlignmentProperties ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1257,7 +1257,7 @@ UTEST( UIHTML, InlineBlockVerticalAlignDoesNotInflateOwnTextLine ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1306,7 +1306,7 @@ UTEST( UIHTMLTable, complexLayout3 ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1339,7 +1339,7 @@ UTEST( UIHTMLTable, nestedPerformance ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1390,7 +1390,7 @@ UTEST( UIHTMLTable, specifiedWidth ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1430,7 +1430,7 @@ UTEST( UIHTMLTable, nestedSpecifiedWidth ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1975,7 +1975,7 @@ UTEST( UIHTMLTable, tableLayoutFixed ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2023,7 +2023,7 @@ UTEST( UIHTMLBody, backgroundColorPropagation ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2100,7 +2100,7 @@ UTEST( UILayout, marginAuto ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2368,7 +2368,7 @@ UTEST( UIHTMLDetails, lobstersInlineBlockCachesWidth ) {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
@@ -2548,7 +2548,7 @@ UTEST( UIBorder, renderingVariations ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2582,7 +2582,7 @@ UTEST( UIBorder, renderingVariations2 ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2610,12 +2610,11 @@ UTEST( UIBorder, renderingVariations2 ) {
}
static UISceneNode* init_test_inline_block() {
FontTrueType* font = nullptr;
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
FontTrueType* monoFont = FontTrueType::New( "monospace" );
FontTrueType* monoFont = FontTrueType::New( "monospace" ).get();
monoFont->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
UISceneNode* sceneNode = UISceneNode::New();
SceneManager::instance()->add( sceneNode );
@@ -4379,7 +4378,7 @@ static UISceneNode* createWinAndLoadHTML( std::string winName, std::string htmlP
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
if ( font == nullptr || !font->loaded() )
return nullptr;
@@ -4447,7 +4446,7 @@ UTEST( FontTrueType, glyphScaleZeroDimensionsNoCrash ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -5326,7 +5325,7 @@ UTEST( UIHTML, RonStonerDeferredImagesUpdateDocumentHeight ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -5416,7 +5415,7 @@ UTEST( UIHTML, NewsBlurStoryArchiveLayoutStabilizes ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
+1 -1
View File
@@ -31,7 +31,7 @@ static UISceneNode* initFormTest( const std::string& title ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
+2 -3
View File
@@ -20,12 +20,11 @@ using namespace EE::Scene;
using namespace EE::UI;
static UISceneNode* init_test_scene_node() {
FontTrueType* font = nullptr;
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
FontFamily::loadFromRegular( font );
FontTrueType* monoFont = FontTrueType::New( "monospace" );
FontTrueType* monoFont = FontTrueType::New( "monospace" ).get();
monoFont->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
UISceneNode* sceneNode = UISceneNode::New();
SceneManager::instance()->add( sceneNode );
+2 -2
View File
@@ -1,9 +1,9 @@
#include "utest.hpp"
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/graphics/richtext.hpp>
#include <eepp/scene/node.hpp>
#include <eepp/scene/scenemanager.hpp>
@@ -39,7 +39,7 @@ static UISceneNode* createRichTextScene() {
32, {}, 1, false, true ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
if ( !font->loaded() ) {
Engine::destroySingleton();
+46 -45
View File
@@ -9,9 +9,9 @@
#include <vector>
#include <eepp/graphics/fontfamily.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/image.hpp>
#include <eepp/graphics/resourcescope.hpp>
#include <eepp/network/http.hpp>
#include <eepp/network/tcplistener.hpp>
#include <eepp/network/tcpsocket.hpp>
@@ -65,7 +65,7 @@ UTEST( UIWebView, OwnedDocumentSceneScrollTarget ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -136,7 +136,7 @@ UTEST( UIWebView, DocumentRootHitTestingTraversesScrollableExtent ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -215,7 +215,7 @@ UTEST( UIWebView, FontSizeEmDoesNotCompoundOnViewportRelayout ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -287,7 +287,7 @@ UTEST( UIWebView, FontFaceWeightSurvivesViewportRelayout ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -369,7 +369,7 @@ UTEST( UIWebView, AbsoluteTextareaPercentageHeightDoesNotRecurse ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -436,7 +436,7 @@ UTEST( UIWebView, RedditLoggedOutCommentSignupTextareaDoesNotGrowWithDocument )
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -575,7 +575,7 @@ UTEST( UIWebView, VerticalScrollbarViewportDoesNotCreateHorizontalScroll ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -660,7 +660,7 @@ UTEST( UIWebView, ExplicitWideDocumentStillCreatesHorizontalScroll ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -713,7 +713,7 @@ UTEST( UIWebView, ExplicitWideDocumentHorizontalScrollReachesRightEdgeAtPixelDen
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -777,7 +777,7 @@ UTEST( UIWebView, ResponsiveDocumentShrinksAfterGrowResize ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -867,7 +867,7 @@ UTEST( UIWebView, HorizontalScrollDisappearsAfterResponsiveShrink ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -951,7 +951,7 @@ UTEST( UIWebView, HiddenAndClippedWideDescendantsDoNotCreateHorizontalScroll ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1019,7 +1019,7 @@ UTEST( UIWebView, VerticalScrollbarDisappearsWithoutViewportWidthOscillation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1090,7 +1090,7 @@ UTEST( UIWebView, HackerNewsGrowUntilVerticalScrollbarDisappearsSettlesViewport
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1147,7 +1147,7 @@ UTEST( UIWebView, HackerNewsFrontPageBottomIsReachable ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1282,7 +1282,7 @@ UTEST( UIWebView, NavigationAfterGrowDoesNotKeepMaximizedWidthOnShrink ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1350,7 +1350,7 @@ UTEST( UIWebView, NavigationFromTallToShortShrinksDocumentExtent ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1414,7 +1414,7 @@ UTEST( UIWebView, AsyncCSSCanShrinkDocumentExtent ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1470,7 +1470,7 @@ UTEST( UIWebView, FixedPositionStaysPinnedToViewportWhenScrolled ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1537,7 +1537,7 @@ UTEST( UIWebView, StickyPositionUsesWebViewViewportWhenScrolled ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1607,7 +1607,7 @@ UTEST( UIWebView, DeferredLocalCSSIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1686,7 +1686,7 @@ UTEST( UIWebView, RemoteCSSIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1793,7 +1793,7 @@ UTEST( UIWebView, RemoteImageIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -1903,7 +1903,7 @@ UTEST( UIWebView, RemoteBackgroundImageIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2025,7 +2025,7 @@ UTEST( UIWebView, LinearGradientRendersToFramebuffer ) {
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
win->setClearColor( Color::Black );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2101,7 +2101,7 @@ UTEST( UIWebView, CoalescesViewportResizeDocumentMetrics ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2152,7 +2152,7 @@ UTEST( UIWebView, HackerNewsSingleStepRestoreSettlesViewportInOneFrame ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2228,7 +2228,7 @@ UTEST( UIWebView, LayoutDrivenResizeKeepsDocumentRootAtViewport ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2468,7 +2468,7 @@ UTEST( UIWebView, DocumentScenesIsolateStylesUriAndLookup ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2574,7 +2574,7 @@ UTEST( UIWebView, DocumentScenesIsolateAuthorFontFaces ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2647,9 +2647,9 @@ UTEST( UIWebView, DocumentScenesIsolateAuthorFontFaces ) {
EXPECT_TRUE( fontA->loaded() );
EXPECT_TRUE( fontB->loaded() );
EXPECT_NE( fontA, fontB );
EXPECT_EQ( nullptr, FontManager::instance()->getByName( "SharedDocFace" ) );
EXPECT_EQ( nullptr, defaultResourceScope().findFont( "SharedDocFace" ).get() );
const std::string fontAResourceName = fontA->getName();
EXPECT_EQ( fontA, FontManager::instance()->getByName( fontAResourceName ) );
EXPECT_EQ( fontA, docA->getResourceScope()->findFont( fontAResourceName ).get() );
webViewA->loadURI( URI( "file://" + pathAWithoutFont ) );
pump();
@@ -2657,7 +2657,7 @@ UTEST( UIWebView, DocumentScenesIsolateAuthorFontFaces ) {
auto targetAWithoutFont = docA->getRoot()->find( "target-a-empty" );
ASSERT_TRUE( targetAWithoutFont != nullptr );
EXPECT_EQ( nullptr, docA->getFontFromNamesList( "SharedDocFace" ) );
EXPECT_EQ( nullptr, FontManager::instance()->getByName( fontAResourceName ) );
EXPECT_EQ( nullptr, docA->getResourceScope()->findFont( fontAResourceName ).get() );
webViewA->loadURI( URI( "file://" + pathA2 ) );
pump();
@@ -2679,7 +2679,7 @@ UTEST( UIWebView, DocumentSceneAuthorFontFacesCleanUpOnDestruction ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2739,14 +2739,15 @@ UTEST( UIWebView, DocumentSceneAuthorFontFacesCleanUpOnDestruction ) {
EXPECT_NE( loadedFontA, loadedFontB );
const std::string loadedFontAName = loadedFontA->getName();
const std::string loadedFontBName = loadedFontB->getName();
EXPECT_EQ( loadedFontA, FontManager::instance()->getByName( loadedFontAName ) );
EXPECT_EQ( loadedFontB, FontManager::instance()->getByName( loadedFontBName ) );
FontWeakPtr loadedFontAWeak = docA->getResourceScope()->findFont( loadedFontAName );
EXPECT_EQ( loadedFontA, docA->getResourceScope()->findFont( loadedFontAName ).get() );
EXPECT_EQ( loadedFontB, docB->getResourceScope()->findFont( loadedFontBName ).get() );
webViewA->close();
pump();
EXPECT_EQ( nullptr, FontManager::instance()->getByName( loadedFontAName ) );
EXPECT_EQ( loadedFontB, FontManager::instance()->getByName( loadedFontBName ) );
EXPECT_TRUE( loadedFontAWeak.expired() );
EXPECT_EQ( loadedFontB, docB->getResourceScope()->findFont( loadedFontBName ).get() );
EXPECT_EQ( loadedFontB, docB->getFontFromNamesList( "DestroyDocFace" ) );
Engine::destroySingleton();
@@ -2759,7 +2760,7 @@ UTEST( UIWebView, RemoteFontFaceIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
const std::string fontPath = Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf";
font->loadFromFile( fontPath );
ASSERT_TRUE( font != nullptr && font->loaded() );
@@ -2873,7 +2874,7 @@ UTEST( UIWebView, StaleRedirectCookieIgnoredAfterNavigation ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -2965,7 +2966,7 @@ UTEST( UIWebView, DestroyWithPendingSubresourcesIsSafe ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
const std::string fontPath = Sys::getProcessPath() + "../assets/fonts/NotoSans-Regular.ttf";
font->loadFromFile( fontPath );
ASSERT_TRUE( font != nullptr && font->loaded() );
@@ -3065,7 +3066,7 @@ UTEST( UIWebView, NewerNavigationSupersedesStartedLoad ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -3114,7 +3115,7 @@ UTEST( UIWebView, CacheGenerationAdvancesWhenReplacementDocumentIsInstalled ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
@@ -3194,7 +3195,7 @@ UTEST( UIWebView, RepeatedRemoteNavigationHandlesSubresourceFanOut ) {
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" ).get();
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );
FontFamily::loadFromRegular( font );
+9 -9
View File
@@ -4261,24 +4261,25 @@ FontTrueType* App::loadFont( const std::string& name, std::string fontPath,
}
if ( fontPath.empty() )
return nullptr;
FontTrueType* font = FontTrueType::New( name );
ResourceScope& resourceScope = defaultResourceScope();
FontTrueTypePtr font = FontTrueType::New( name, resourceScope );
if ( font->loadFromFile( fontPath ) ) {
font->setHinting( mConfig.ui.fontHinting );
font->setAntialiasing( mConfig.ui.fontAntialiasing );
return font;
return font.get();
}
eeSAFE_DELETE( font );
resourceScope.eraseLocalFont( font.get() );
// Failed to load original font? Try to fallback
if ( !fallback.empty() && !wasFallback ) {
if ( !fontPath.empty() && FileSystem::isRelativePath( fontPath ) )
fontPath = mResPath + fontPath;
font = FontTrueType::New( name );
font = FontTrueType::New( name, resourceScope );
if ( font->loadFromFile( fontPath ) ) {
font->setHinting( mConfig.ui.fontHinting );
font->setAntialiasing( mConfig.ui.fontAntialiasing );
return font;
return font.get();
}
eeSAFE_DELETE( font );
resourceScope.eraseLocalFont( font.get() );
}
return nullptr;
}
@@ -4533,12 +4534,12 @@ void App::init( InitParameters& params ) {
mFallbackFont = loadFont( "fallback-font", "fonts/DroidSansFallbackFull.ttf" );
if ( mFallbackFont )
FontManager::instance()->addFallbackFont( mFallbackFont );
defaultResourceScope().getFontService().addFallbackFont( mFallbackFont );
if ( mConfig.ui.fallbackFont != "fonts/DroidSansFallbackFull.ttf" ) {
mUserFallbackFont = loadFont( "fallback-font", mConfig.ui.fallbackFont );
if ( mUserFallbackFont )
FontManager::instance()->addFallbackFont( mUserFallbackFont );
defaultResourceScope().getFontService().addFallbackFont( mUserFallbackFont );
}
Log::info( "Fonts loaded in: %s", fontsClock.getElapsedTime().toString() );
@@ -4812,7 +4813,6 @@ void App::init( InitParameters& params ) {
mAsyncResourcesLoadCond.wait( syntaxLanguagesLock,
[this]() { return mAsyncResourcesLoaded; } );
}
if ( !mFont || !mFontMono || !mRemixIconFont || !mNoniconsFont || !mCodIconFont ) {
printf( "Font not found!" );
Log::error( "Font not found!" );
+35 -20
View File
@@ -14,7 +14,7 @@ struct MonospaceFontPreview {
std::string previewPath;
FontTrueType* originalFont{ nullptr };
bool confirmed{ false };
UnorderedMap<std::string, FontTrueType*> loadedFonts;
UnorderedMap<std::string, FontTrueTypePtr> loadedFonts;
};
void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMonoFont,
@@ -29,7 +29,8 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
return path;
};
const auto applyMonospaceFont = [this, terminalFont]( FontTrueType* fontMono ) {
const auto applyMonospaceFont = [this, terminalFont]( FontTrueType* fontMono,
bool loadFamily = false ) {
if ( !fontMono )
return;
@@ -40,7 +41,10 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
fontMono->setEnableDynamicMonospace( true );
fontMono->setBoldAdvanceSameAsRegular( true );
FontFamily::loadFromRegular( fontMono );
// Related faces are published by FontFamily. Keep transient previews isolated and only
// publish/load their family after the user confirms the selection.
if ( loadFamily )
FontFamily::loadFromRegular( fontMono );
if ( !mApp->getSplitter() )
return;
@@ -75,21 +79,30 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
: mApp->getFontMono() );
}
const auto loadPreviewFont = [this, preview]( const std::string& newPath ) -> FontTrueType* {
const auto loadPreviewFont = [this, preview]( const FontDesc& desc ) -> FontTrueTypePtr {
if ( !preview )
return nullptr;
return {};
auto found = preview->loadedFonts.find( newPath );
auto found = preview->loadedFonts.find( desc.path );
if ( found != preview->loadedFonts.end() )
return found->second;
auto fontName = FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( newPath ) );
FontTrueType* fontMono = mApp->loadFont( fontName, newPath );
if ( fontMono )
preview->loadedFonts[newPath] = fontMono;
FontTrueTypePtr fontMono = defaultResourceScope().getFontService().loadSystemFont( desc );
if ( fontMono ) {
fontMono->setHinting( mApp->getConfig().ui.fontHinting );
fontMono->setAntialiasing( mApp->getConfig().ui.fontAntialiasing );
preview->loadedFonts[desc.path] = fontMono;
}
return fontMono;
};
const auto publishPreviewFont = []( const std::string& path, const FontTrueTypePtr& font ) {
if ( !font )
return;
auto fontName = FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) );
defaultResourceScope().publishLocalFont( std::move( fontName ), font );
};
const Uint32 flags = UIFontPickerDialog::DefaultFlags |
( loadingMonoFont ? UIFontPickerDialog::MonospaceOnly : 0 );
UIFontPickerDialog* dialog = UIFontPickerDialog::New( flags );
@@ -97,7 +110,7 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
dialog->setCloseShortcut( KEY_ESCAPE );
dialog->on( Event::OnWindowClose, [this, preview, applyMonospaceFont]( const Event* ) {
if ( preview && !preview->confirmed )
applyMonospaceFont( preview->originalFont );
applyMonospaceFont( preview->originalFont, false );
if ( App::instance() && mApp->getSplitter() && mApp->getSplitter()->getCurWidget() &&
!SceneManager::instance()->isShuttingDown() ) {
@@ -113,20 +126,20 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
return;
if ( newPath == preview->originalPath ) {
applyMonospaceFont( preview->originalFont );
applyMonospaceFont( preview->originalFont, false );
preview->previewPath = newPath;
return;
}
FontTrueType* fontMono = loadPreviewFont( newPath );
FontTrueTypePtr fontMono = loadPreviewFont( selection.font );
if ( fontMono ) {
applyMonospaceFont( fontMono );
applyMonospaceFont( fontMono.get(), false );
preview->previewPath = newPath;
}
} );
}
dialog->setOnFontPicked( [&fontPath, loadingMonoFont, onFinish, preview, normalizedFontPath,
loadPreviewFont,
loadPreviewFont, publishPreviewFont,
applyMonospaceFont]( const UIFontSelection& selection ) {
auto newPath = normalizedFontPath( selection.font.path );
if ( newPath.empty() )
@@ -139,18 +152,20 @@ void FontPickerController::openFontDialog( std::string& fontPath, bool loadingMo
return;
}
FontTrueType* fontMono = preview && newPath == preview->originalPath
? preview->originalFont
: loadPreviewFont( newPath );
FontTrueTypePtr previewFont = preview && newPath != preview->originalPath
? loadPreviewFont( selection.font )
: FontTrueTypePtr{};
FontTrueType* fontMono = previewFont ? previewFont.get() : preview->originalFont;
if ( fontMono ) {
fontPath = newPath;
if ( preview )
preview->confirmed = true;
applyMonospaceFont( fontMono );
publishPreviewFont( newPath, previewFont );
applyMonospaceFont( fontMono, previewFont != nullptr );
}
} else if ( preview ) {
preview->confirmed = true;
applyMonospaceFont( preview->originalFont );
applyMonospaceFont( preview->originalFont, false );
}
} );
dialog->setSelectedFont( absoluteFontPath );
+3 -2
View File
@@ -3163,7 +3163,7 @@ UIMenu* SettingsMenu::createFontHintMenu() {
if ( String::startsWith( id, "hint_" ) ) {
auto hint = id.substr( 5 ).toUtf8();
mApp->getConfig().ui.fontHinting = FontTrueType::fontHintingFromString( hint );
FontManager::instance()->setHinting( mApp->getConfig().ui.fontHinting );
defaultResourceScope().getFontService().setHinting( mApp->getConfig().ui.fontHinting );
}
} );
@@ -3204,7 +3204,8 @@ UIMenu* SettingsMenu::createFontAntiAliasingMenu() {
auto hint = id.substr( 3 ).toUtf8();
mApp->getConfig().ui.fontAntialiasing =
FontTrueType::fontAntialiasingFromString( hint );
FontManager::instance()->setAntialiasing( mApp->getConfig().ui.fontAntialiasing );
defaultResourceScope().getFontService().setAntialiasing(
mApp->getConfig().ui.fontAntialiasing );
}
} );
+4 -4
View File
@@ -276,7 +276,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
FontTrueType* fontMono = nullptr;
if ( fontPath && FileSystem::fileExists( fontPath.Get() ) ) {
FileInfo file( fontPath.Get() );
fontMono = FontTrueType::New( "monospace" );
fontMono = FontTrueType::New( "monospace" ).get();
if ( fontMono->loadFromFile( file.getFilepath() ) ) {
FontFamily::loadFromRegular( fontMono );
} else {
@@ -284,7 +284,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
}
}
if ( fontMono == nullptr ) {
fontMono = FontTrueType::New( "monospace" );
fontMono = FontTrueType::New( "monospace" ).get();
fontMono->loadFromFile( resPath + "fonts/DejaVuSansMonoNerdFontComplete.ttf" );
FontFamily::loadFromRegular( fontMono, "DejaVuSansMono" );
}
@@ -301,9 +301,9 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
? fallbackFontPathF.Get()
: resPath + "fonts/DroidSansFallbackFull.ttf" );
if ( FileSystem::fileExists( fallbackFontPath ) ) {
FontTrueType* fallbackFont = FontTrueType::New( "fallback-font" );
FontTrueType* fallbackFont = FontTrueType::New( "fallback-font" ).get();
if ( fallbackFont->loadFromFile( fallbackFontPath ) )
FontManager::instance()->addFallbackFont( fallbackFont );
defaultResourceScope().getFontService().addFallbackFont( fallbackFont );
}
Float realMaxFPS = maxFPS.Get() ? maxFPS.Get() : currentDisplay->getRefreshRate();
+5 -4
View File
@@ -105,11 +105,12 @@ EE_MAIN_FUNC int main( int, char*[] ) {
else if ( PixelDensity::getPixelDensity() >= 2.f )
pd = "2x";
FontTrueType* font = FontTrueType::New( "NotoSans-Regular",
resPath + "assets/fonts/NotoSans-Regular.ttf" );
FontTrueTypePtr font = FontTrueType::New( "NotoSans-Regular",
resPath + "assets/fonts/NotoSans-Regular.ttf",
*uiSceneNode->getResourceScope() );
UITheme* theme = UITheme::load( "uitheme" + pd, "uitheme" + pd,
resPath + "assets/ui/uitheme" + pd + ".eta", font,
resPath + "assets/ui/uitheme" + pd + ".eta", font.get(),
resPath + "assets/ui/uitheme.css" );
/*UITheme* theme =
@@ -120,7 +121,7 @@ EE_MAIN_FUNC int main( int, char*[] ) {
uiSceneNode->getUIThemeManager()
->setDefaultEffectsEnabled( true )
->setDefaultTheme( theme )
->setDefaultFont( font )
->setDefaultFont( font.get() )
->add( theme );
}
@@ -109,21 +109,22 @@ EE_MAIN_FUNC int main( int, char*[] ) {
else if ( PixelDensity::getPixelDensity() >= 2.f )
pd = "2x";
FontTrueType* font = FontTrueType::New( "NotoSans-Regular",
resPath + "assets/fonts/NotoSans-Regular.ttf" );
FontTrueTypePtr font = FontTrueType::New( "NotoSans-Regular",
resPath + "assets/fonts/NotoSans-Regular.ttf",
*uiSceneNode->getResourceScope() );
/*UITheme* theme = UITheme::load( "uitheme" + pd, "uitheme" + pd, resPath +
* "assets/ui/uitheme" + pd + ".eta", font, resPath + "assets/ui/uitheme.css" );*/
UITheme* theme =
UITheme::load( "uitheme", "uitheme", "", font, resPath + "assets/ui/breeze.css" );
UITheme* theme = UITheme::load( "uitheme", "uitheme", "", font.get(),
resPath + "assets/ui/breeze.css" );
uiSceneNode->combineStyleSheet( theme->getStyleSheet() );
uiSceneNode->getUIThemeManager()
->setDefaultEffectsEnabled( true )
->setDefaultTheme( theme )
->setDefaultFont( font )
->setDefaultFont( font.get() )
->add( theme );
}
+15 -11
View File
@@ -142,7 +142,7 @@ void App::unloadImages() {
void App::unloadFonts() {
for ( auto it = mFontsLoaded.begin(); it != mFontsLoaded.end(); ++it )
FontManager::instance()->remove( it->first );
mUISceneNode->getResourceScope()->eraseLocalFont( it->first.get() );
mFontsLoaded.clear();
}
@@ -168,7 +168,9 @@ FontTrueType* App::loadFont( const std::string& name, std::string fontPath,
}
if ( fontPath.empty() )
return nullptr;
return FontTrueType::New( name, fontPath );
FontTrueTypePtr font = FontTrueType::New( name, fontPath, *mUISceneNode->getResourceScope() );
mFontsLoaded[font] = name;
return font.get();
}
void App::createWidgetInspector() {
@@ -179,7 +181,7 @@ void App::createWidgetInspector() {
void App::loadFont( std::string path ) {
std::string filename( FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( path ) ) );
FontTrueType* font = FontTrueType::New( filename );
FontTrueTypePtr font = FontTrueType::New( filename, *mUISceneNode->getResourceScope() );
font->loadFromFile( path );
mFontsLoaded[font] = filename;
}
@@ -614,7 +616,7 @@ void App::onLayoutSelected( const Event* event ) {
UIMenuCheckBox* chk = static_cast<UIMenuCheckBox*>( event->getNode() );
chk->setActive( true );
std::map<std::string, std::string>::iterator it;
UnorderedMap<std::string, std::string>::iterator it;
if ( ( it = mLayouts.find( txt.toUtf8() ) ) != mLayouts.end() )
loadLayout( it->second );
@@ -1271,16 +1273,16 @@ void App::init( const Float& pixelDensityConf, const bool& useAppTheme, const st
mResPath += "assets";
FileSystem::dirAddSlashAtEnd( mResPath );
FontTrueType* font =
FontTrueTypePtr font =
FontTrueType::New( "NotoSans-Regular", mResPath + "fonts/NotoSans-Regular.ttf" );
FontTrueType* fontMono =
FontTrueTypePtr fontMono =
FontTrueType::New( "monospace", mResPath + "fonts/DejaVuSansMono.ttf" );
FontFamily::loadFromRegular( font );
FontFamily::loadFromRegular( fontMono );
FontFamily::loadFromRegular( font.get() );
FontFamily::loadFromRegular( fontMono.get() );
mBaseStyleSheet = mResPath + "ui/breeze.css";
mTheme = UITheme::load( "uitheme", "uitheme", "", font, mBaseStyleSheet );
mTheme = UITheme::load( "uitheme", "uitheme", "", font.get(), mBaseStyleSheet );
mUISceneNode = UISceneNode::New();
mUISceneNode->setId( "uiSceneNode" );
@@ -1311,10 +1313,12 @@ void App::init( const Float& pixelDensityConf, const bool& useAppTheme, const st
mAppUISceneNode->getUIThemeManager()
->setDefaultEffectsEnabled( true )
->setDefaultTheme( mTheme )
->setDefaultFont( font )
->setDefaultFont( font.get() )
->add( mTheme );
mUISceneNode->getUIThemeManager()->setDefaultFont( font )->setDefaultEffectsEnabled( true );
mUISceneNode->getUIThemeManager()
->setDefaultFont( font.get() )
->setDefaultEffectsEnabled( true );
mAppUISceneNode->getUIIconThemeManager()->setCurrentTheme( iconTheme );
+4 -4
View File
@@ -184,18 +184,18 @@ class App : public UICodeEditorSplitter::Client {
efsw::WatchID mWatch{ 0 };
efsw::WatchID mStyleSheetWatch{ 0 };
efsw::WatchID mBaseStyleSheetWatch{ 0 };
std::map<std::string, std::string> mWidgetRegistered;
UnorderedMap<std::string, std::string> mWidgetRegistered;
std::string mResPath;
std::string mBasePath;
UIConsole* mConsole{ nullptr };
std::map<std::string, std::string> mLayouts;
UnorderedMap<std::string, std::string> mLayouts;
std::vector<std::string> mRecentProjects;
std::vector<std::string> mRecentFiles;
IniFile mIni;
Uint32 mRecentProjectEventClickId{ 0xFFFFFFFF };
Uint32 mRecentFilesEventClickId{ 0xFFFFFFFF };
std::map<ResourceId, TextureRegionPtr> mImagesLoaded;
std::map<Font*, std::string> mFontsLoaded;
UnorderedMap<ResourceId, TextureRegionPtr> mImagesLoaded;
UnorderedMap<FontPtr, std::string> mFontsLoaded;
UpdateListener* mListener{ nullptr };
std::string mConfigPath;
std::string mColorSchemesPath;