Skip to content

Commit

Permalink
FontLoader can choose proper font file; Fix choosing eqivalent FontWe…
Browse files Browse the repository at this point in the history
…ights
  • Loading branch information
nieznanysprawiciel committed Nov 17, 2024
1 parent bd64fe4 commit 933265e
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 16 deletions.
4 changes: 1 addition & 3 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ EmptyLineAfterAccessModifier: Leave
# Describe the regular expression of the comment with special meaning, it should not be divided into multiple lines or changed in other ways
# CommentPragmas:'^ IWYU pragma:'
# The initialization list of the constructor is either all on the same line or on their own line
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# The comfort list of constructors all wrap
AllowAllConstructorInitializersOnNextLine: false
AllowAllConstructorInitializersOnNextLine: true
# The indentation width of the initialization list of the constructor
ConstructorInitializerIndentWidth: 4
# The indentation width of the continued line
Expand Down
10 changes: 9 additions & 1 deletion swGraphicAPI/Assets/TextAsset/Loader/FontAssetInitData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,12 @@ float FontLayout::SpaceWidth() const { return (float)Glyphs.at( L'0' )

float FontLayout::NewLineSize() const { return (float)Glyphs.at( L'0' ).Height; }

} // sw
// ================================ //

std::string ChooseFontLoadData::ResourceKey() const
{
return fmt::format( "/Font?fontSize={},family={},weight={},style={}", this->FontSize, this->FontFamily,
this->FontWeight, this->FontStyle );
}

} // namespace sw
24 changes: 24 additions & 0 deletions swGraphicAPI/Assets/TextAsset/Loader/FontAssetInitData.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,30 @@ struct FontLoaderData : public IAssetLoadInfo

};

/**@brief Load font by providing parameters which will be resolved by FontPicker.
@ingroup Text*/
struct ChooseFontLoadData : public FontLoaderData
{
RTTR_ENABLE( FontLoaderData );
public:

std::string FontFamily;
FontWeight FontWeight;
FontStyle FontStyle;
bool MatchExact;

public:
explicit ChooseFontLoadData( const std::string& fontFamuly, FontSizeType fontSize )
: FontLoaderData( fontSize )
, FontFamily( fontFamuly )
, FontWeight( FontWeight::Normal )
, FontStyle( FontStyle::Normal )
, MatchExact( true )
{}

public:
virtual std::string ResourceKey() const override;
};



Expand Down
42 changes: 34 additions & 8 deletions swGraphicAPI/Assets/TextAsset/Loader/FontLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ Nullable< std::map<KerningPair, float> > BuildKerning( const FreeTypeLibr
return collector.Return( kerning );
}

// ================================ //

FreeTypeLoader::FreeTypeLoader( FontPicker&& picker ) : m_fontPicker( std::move( picker ) ) {}

// ================================ //
//
Expand All @@ -77,7 +80,11 @@ bool FreeTypeLoader::CanLoad( const AssetPath& filePath, TypeID r
TypeID::get< Resource >()
};

return DefaultCanLoad( filePath, resourceType, allowedExtensions, allowedTypes );
// Variant for ChooseFontLoadData descriptor.
if( filePath.GetFile().IsEmpty() )
return CanLoadType( resourceType, allowedTypes );
else
return DefaultCanLoad( filePath, resourceType, allowedExtensions, allowedTypes );
}

// ================================ //
Expand All @@ -87,21 +94,40 @@ LoadingResult FreeTypeLoader::Load( const LoadPath& filePath, TypeID resou
if( assetDesc == nullptr )
return LoaderException::Create( "FreeTypeLoader", "Asset descriptor is null.", filePath, resourceType );

if( assetDesc->get_type() != TypeID::get< FontLoaderData >() )
return LoaderException::Create( "FreeTypeLoader", "Unsupported descriptor type [ " + assetDesc->get_type().get_name().to_string() + " ].", filePath, resourceType );
if( assetDesc->get_type() != TypeID::get< FontLoaderData >()
&& assetDesc->get_type() != TypeID::get< ChooseFontLoadData >() )
{
return LoaderException::Create(
"FreeTypeLoader", "Unsupported descriptor type [ " + assetDesc->get_type().get_name().to_string() + " ].",
filePath, resourceType );
}

LoadPath fontPath = filePath;
if( assetDesc->get_type() == TypeID::get< ChooseFontLoadData >() )
{
auto loadInfo = static_cast< const ChooseFontLoadData* >( assetDesc );
auto chosen =
m_fontPicker.ChooseFontFile( context.GetPathsManager(), loadInfo->FontFamily, loadInfo->FontWeight, loadInfo->FontStyle, loadInfo->MatchExact );
ReturnIfInvalid( chosen );

fontPath = chosen.Get().Path;
}

auto loadInfo = static_cast< const FontLoaderData* >( assetDesc );

AssetPath atlasPath = AssetPath( filePath.GetFileTranslated(), fmt::format( "/Atlas{}", loadInfo->ResourceKey() ) );
AssetPath fontAssetPath = AssetPath( filePath.GetFileTranslated(), loadInfo->ResourceKey() );
// Note: ResourceKey is taken from parent descriptor, because since we have exact file path, we don't need to distinguish
// between different styles and weights. The goal of havinf internal path is to avoid duplicate loading of the same font.
AssetPath atlasPath =
AssetPath( fontPath.GetFileTranslated(), fmt::format( "/Atlas{}", loadInfo->FontLoaderData::ResourceKey() ) );
AssetPath fontAssetPath = AssetPath( fontPath.GetFileTranslated(), loadInfo->FontLoaderData::ResourceKey() );

auto cached = context.GetCachedGeneric( fontAssetPath, resourceType );
if( cached )
return LoadingResult( cached );

auto freeType = FreeTypeLibrary::Create();
ReturnIfInvalid( freeType );
ReturnIfInvalid( freeType.Get().CreateFace( filePath, loadInfo->FontSize ) );
ReturnIfInvalid( freeType.Get().CreateFace( fontPath, loadInfo->FontSize ) );

FontInitData fontDesc( loadInfo->FontSize );

Expand All @@ -118,7 +144,7 @@ LoadingResult FreeTypeLoader::Load( const LoadPath& filePath, TypeID resou
}
catch( const RuntimeException& ex )
{
return LoaderException::Create( "FreeTypeLoader", ex.ErrorMessage(), filePath, resourceType );
return LoaderException::Create( "FreeTypeLoader", ex.ErrorMessage(), fontPath, resourceType );
}
}

Expand Down Expand Up @@ -154,7 +180,7 @@ Nullable< TexturePtr > FreeTypeLoader::RenderAtlas( const FreeTypeLibrary&
//SoilTextureLoader::Save( filePath.GetFile().ChangeExtension( ".png" ), image );

TextureInitData texInfo( std::move( image ) );
texInfo.MipMaps = MipMapsInfo( MipMapFilter::Lanczos3 );
texInfo.MipMaps = MipMapsInfo();
texInfo.TextureUsage = TextureUsageInfo();
texInfo.Format = ResourceFormat::RESOURCE_FORMAT_R8G8B8A8_UNORM;

Expand Down
9 changes: 7 additions & 2 deletions swGraphicAPI/Assets/TextAsset/Loader/FontLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "swGraphicAPI/ResourceManager/Loaders/IAssetLoadInfo.h"
#include "swGraphicAPI/ResourceManager/Loaders/IAssetLoader.h"
#include "swGraphicAPI/Assets/TextAsset/Loader/FontPicker.h"


namespace sw
Expand All @@ -26,9 +27,13 @@ class FreeTypeLibrary;
class FreeTypeLoader : public IAssetLoader
{
protected:

FontPicker m_fontPicker;

public:
explicit FreeTypeLoader () = default;
virtual ~FreeTypeLoader () = default;
explicit FreeTypeLoader () = default;
explicit FreeTypeLoader ( FontPicker&& picker );
virtual ~FreeTypeLoader () = default;

virtual bool CanLoad ( const AssetPath& filePath, TypeID resourceType ) override;
virtual LoadingResult Load ( const LoadPath& filePath, TypeID resourceType, const IAssetLoadInfo* assetDesc, RMLoaderAPI context ) override;
Expand Down
2 changes: 1 addition & 1 deletion swGraphicAPI/Assets/TextAsset/Loader/FontPicker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Nullable< FontSearchEntry > FontPicker::ChooseFontFile( PathsManager* pm, co

for( auto& variant : variants.Get() )
{
if( variant.Metadata.Weight == weight && variant.Metadata.Style == style )
if( Eqivalent( variant.Metadata.Weight, weight ) && Eqivalent( variant.Metadata.Style, style ) )
return variant;

metric[ &variant ] =
Expand Down
12 changes: 12 additions & 0 deletions swGraphicAPI/Assets/TextAsset/Loader/FontPicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,18 @@ inline bool operator>( const FontStyle& left, const FontStyle& right )
return static_cast< u8 >( left ) > static_cast< u8 >( right );
}

/**@brief Checks if enum variants can be treated as equal.*/
inline bool Eqivalent( const FontStyle& left, const FontStyle& right )
{
return FontPicker::ClosenessMetric( left ) == FontPicker::ClosenessMetric( right );
}

/**@brief Checks if enum variants can be treated as equal.*/
inline bool Eqivalent( const FontWeight& left, const FontWeight& right )
{
return FontPicker::ClosenessMetric( left ) == FontPicker::ClosenessMetric( right );
}

} // sw

DEFINE_FMT_FORMATTER_ENUM( sw::FontWeight );
Expand Down
1 change: 1 addition & 0 deletions swGraphicAPI/ResourceManager/Loaders/RMLoaderAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class RMLoaderAPI : protected ResourceManagerAPI
using ResourceManagerAPI::LoadComputeShader;
using ResourceManagerAPI::LoadShader;

using ResourceManagerAPI::GetPathsManager;
};


Expand Down
26 changes: 26 additions & 0 deletions swGraphicAPI/Tests/TestText/TestFontLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,29 @@ TEST_CASE( "GraphicAPI.Loaders.Correctness.ExitingAtlas", "[GraphicAPI][FontLoad
REQUIRE_IS_VALID( font2 );
}

// ================================ //
//
TEST_CASE( "GraphicAPI.Loaders.PickFont", "[GraphicAPI][FontLoader][FreeTypeLoader]" )
{
auto rm = CreateResourceManagerWithMocksAndDefaults();
auto pm = rm->GetPathsManager();

FontPicker picker;
picker.RegisterSearchPath( "$(FontAssets)" );
pm->RegisterAlias( "$(FontAssets)", "$(TestAssets)/fonts/" );

rm->RegisterLoader( std::make_shared< FreeTypeLoader >( std::move( picker ) ) );
rm->RegisterAssetCreator( FontCreator::CreateCreator() );

ChooseFontLoadData init( "Arial", 16 );
init.FontWeight = FontWeight::Normal;
init.FontStyle = FontStyle::Normal;

auto api = ResourceManagerAPI( rm.get() );
auto font = api.Load< FontAsset >( "", &init );
REQUIRE_IS_VALID( font );

CHECK( font.Get()->GetMetadata().Family == "Arial" );
CHECK( font.Get()->GetMetadata().Style == FontStyle::Normal );
CHECK( font.Get()->GetMetadata().Weight == FontWeight::Regular ); // Regular is eqivalent to Normal
}
6 changes: 5 additions & 1 deletion swGraphicAPI/Tests/TestText/TestFontPicker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ TEST_CASE( "GraphicAPI.Loaders.Font.FontPicker.ChooseFont", "[GraphicAPI][FontLo
chosen = picker.ChooseFontFile( rm->GetPathsManager(), "Source Sans Pro", FontWeight::Light, FontStyle::Italic, true );
REQUIRE_INVALID( chosen );

// DemiBold is eqivalent to SemiBold so exact match should be found.
chosen = picker.ChooseFontFile( rm->GetPathsManager(), "Source Sans Pro", FontWeight::DemiBold, FontStyle::Normal, true );
REQUIRE_IS_VALID( chosen );

chosen = picker.ChooseFontFile( rm->GetPathsManager(), "Source Sans Pro", FontWeight::Light, FontStyle::Italic, false );
REQUIRE_IS_VALID( chosen );
CHECK( chosen.Get().Metadata.Weight == FontWeight::ExtraLight );
Expand Down Expand Up @@ -191,7 +195,7 @@ TEST_CASE( "GraphicAPI.Loaders.Font.FontPicker.ParseStyle", "[GraphicAPI][FontLo

result = FontPicker::ParseFontStyle( "Condensed Bold" );
REQUIRE_IS_VALID( result );
CHECK( result.Get() == FontStyle::Normal );
CHECK( result.Get() == FontStyle::Condensed );

result = FontPicker::ParseFontStyle( "Condensed Bold Italic" );
REQUIRE_IS_VALID( result );
Expand Down

0 comments on commit 933265e

Please sign in to comment.