Fixes in Color::isColorString, added some functions to String, refactored a few things in LuaPattern. Fixed a crash while rendering text with only spaces. Improved FunctionString performance.

This commit is contained in:
Martín Lucas Golini
2026-04-07 00:05:51 -03:00
parent 1be1137ebd
commit 5e6c05d0c5
17 changed files with 285 additions and 127 deletions
+6
View File
@@ -117,6 +117,12 @@ table, td {
text-align: left;
}
hr {
min-height: 1dp;
background-color: gray;
margin: 0.5em 0;
}
center {
text-align: center;
}
+21
View File
@@ -88,6 +88,15 @@ class EE_API String {
return hash;
}
static constexpr String::HashType hashToLower( const char* str, Int64 len ) {
String::HashType hash = 5381;
while ( --len >= 0 ) {
int c = *str++;
hash = ( ( hash << 5 ) + hash ) + ( c >= 'A' && c <= 'Z' ? c + 32 : c );
}
return hash;
}
/** Escape string sequence */
static String escape( const String& str );
@@ -104,6 +113,18 @@ class EE_API String {
* String( "text" ) ) */
static String::HashType hash( const String& str );
/** @return string hash to lower. Assumes ASCII */
static String::HashType hashToLower( const std::string& str );
/** @return string hash to lower. Assumes ASCII */
static String::HashType hashToLower( const std::string_view& str );
/** @return string hash to lower. Assumes ASCII */
static String::HashType hashToLower( const String::View& str );
/** @return string hash to lower. Assumes ASCII */
static String::HashType hashToLower( const String& str );
/** @return If the value passed is a character */
static bool isCharacter( const int& value );
+6 -1
View File
@@ -5,6 +5,7 @@
#include <eepp/core/containers.hpp>
#include <eepp/core/string.hpp>
#include <eepp/system/bitop.hpp>
#include <eepp/system/functionstring.hpp>
#include <array>
#include <string>
@@ -220,7 +221,7 @@ class EE_API Color : public tColor<Uint8> {
static Color fromString( std::string str );
static bool isColorString( std::string str, bool searchColorNames = true );
static bool isColorString( std::string_view str, bool searchColorNames = true );
static bool isColorString( String::View str, bool searchColorNames = true );
@@ -400,9 +401,13 @@ class EE_API Color : public tColor<Uint8> {
private:
static UnorderedMap<std::string, Color> sColors;
static UnorderedMap<String::HashType, Color> sColorHash;
static UnorderedMap<String::HashType, Color> sColorMap;
static void initColorMap();
template <AllowedFunctionString StringType>
static bool isColorStringT( StringType str, bool searchColorNames );
};
typedef Color ColorA;
+24 -7
View File
@@ -2,21 +2,36 @@
#define EE_SYSTEM_FUNCTIONSTRING_HPP
#include <eepp/config.hpp>
#include <eepp/core/small_vector.hpp>
#include <eepp/core/string.hpp>
#include <concepts>
#include <string>
#include <vector>
template <typename T>
concept AllowedFunctionString =
std::same_as<T, std::string_view> || std::same_as<T, EE::String::View>;
namespace EE { namespace System {
class EE_API FunctionString {
public:
static FunctionString parse( const std::string& function );
using Parameters = SmallVector<std::string, 4>;
using TypeStringVector = SmallVector<bool, 4>;
FunctionString( const std::string& name, const std::vector<std::string>& parameters,
const std::vector<bool>& typeStringData );
static FunctionString parse( std::string_view function );
static FunctionString parse( String::View function );
FunctionString( const std::string& name, const Parameters& parameters,
const TypeStringVector& typeStringData );
FunctionString( const std::string& name, Parameters&& parameters,
TypeStringVector&& typeStringData );
const std::string& getName() const;
const std::vector<std::string>& getParameters() const;
const Parameters& getParameters() const;
bool parameterWasString( Uint32 index ) const;
@@ -24,8 +39,10 @@ class EE_API FunctionString {
protected:
std::string name;
std::vector<std::string> parameters;
std::vector<bool> typeStringData;
Parameters parameters;
TypeStringVector typeStringData;
template <AllowedFunctionString StringType> static FunctionString parse( StringType function );
};
}} // namespace EE::System
+4 -4
View File
@@ -15,13 +15,13 @@ class EE_API LuaPattern : public PatternMatcher {
static std::string_view getURIPattern();
static std::string matchesAny( const std::vector<std::string>& stringvec,
const std::string_view& pattern );
std::string_view pattern );
static std::string match( const std::string& string, const std::string_view& pattern );
static std::string match( std::string_view string, std::string_view pattern );
static Range firstMatch( const std::string& string, const std::string_view& pattern );
static Range firstMatch( std::string_view string, std::string_view pattern );
static bool hasMatches( const std::string& string, const std::string_view& pattern );
static bool hasMatches( std::string_view string, std::string_view pattern );
LuaPattern( std::string_view pattern, Uint32 options = Options::None );
+2
View File
@@ -28,6 +28,8 @@ class EE_API UIRichText : public UILayout {
static UIRichText* NewBr();
static UIRichText* NewHr();
static UIRichText* NewDiv() { return UIRichText::NewWithTag( "div" ); };
static UIRichText* NewPre() { return UIRichText::NewWithTag( "pre" ); };
+23 -1
View File
@@ -658,6 +658,27 @@ String::HashType String::hash( const String& str ) {
str.size() * sizeof( String::StringBaseType ) );
}
String::HashType String::hashToLower( const std::string& str ) {
return String::hashToLower( str.c_str(), str.length() );
}
String::HashType String::hashToLower( const std::string_view& str ) {
return String::hashToLower( str.data(), str.length() );
}
String::HashType String::hashToLower( const String::View& str ) {
String::HashType hash = 5381;
for ( size_t i = 0; i < str.size(); ++i ) {
int c = str[i];
hash = ( ( hash << 5 ) + hash ) + ( c >= 'A' && c <= 'Z' ? c + 32 : c );
}
return hash;
}
String::HashType String::hashToLower( const String& str ) {
return String::hashToLower( str.view() );
}
bool String::isCharacter( const int& value ) {
return ( value >= 32 && value <= 126 ) || ( value >= 161 && value <= 255 ) || ( value == 9 );
}
@@ -1332,7 +1353,8 @@ bool String::istartsWith( String::View haystack, String::View needle ) {
bool String::istartsWith( const char* haystack, const char* needle ) {
size_t needleLen = strlen( needle );
if ( needleLen > strlen( haystack ) ) return false;
if ( needleLen > strlen( haystack ) )
return false;
return std::equal( needle, needle + needleLen, haystack, []( char c1, char c2 ) {
return std::tolower( c1 ) == std::tolower( c2 );
} );
+3
View File
@@ -1703,6 +1703,9 @@ void Text::draw( const Float& X, const Float& Y, const Vector2f& scale, const Fl
return;
}
if ( mColors.empty() )
return;
Texture* texture = mFontStyleConfig.Font->getTexture( mFontStyleConfig.CharacterSize );
if ( !texture )
return;
+84 -66
View File
@@ -1,5 +1,6 @@
#include <eepp/system/color.hpp>
#include <eepp/system/functionstring.hpp>
#include <eepp/system/luapattern.hpp>
#include <cmath>
#include <cstdlib>
@@ -18,6 +19,7 @@ template <typename T> inline T _round( T r ) {
} // namespace
UnorderedMap<std::string, Color> Color::sColors;
UnorderedMap<String::HashType, Color> Color::sColorHash;
UnorderedMap<String::HashType, Color> Color::sColorMap;
// Keep the old defined colors
@@ -686,10 +688,10 @@ Color Color::fromString( std::string str ) {
return Color::Transparent;
}
} else if ( String::startsWith( str, "@color/" ) ) {
std::string colorName( String::toLower( str.substr( 7 ) ) );
const auto& it = sColors.find( colorName );
std::string_view colorName( std::string_view( str ).substr( 7 ) );
const auto& it = sColorHash.find( String::hashToLower( colorName ) );
if ( it != sColors.end() ) {
if ( it != sColorHash.end() ) {
return it->second;
} else {
return Color::Transparent;
@@ -701,10 +703,9 @@ Color Color::fromString( std::string str ) {
if ( it != sColorMap.end() )
return it->second;
} else {
String::toLowerInPlace( str );
const auto& it = sColors.find( str );
const auto& it = sColorHash.find( String::hashToLower( str ) );
if ( it != sColors.end() ) {
if ( it != sColorHash.end() ) {
return it->second;
} else {
return Color::Transparent;
@@ -714,42 +715,8 @@ Color Color::fromString( std::string str ) {
return Color::Transparent;
}
bool Color::isColorString( std::string str, bool searchColorNames ) {
if ( str.empty() )
return false;
if ( str[0] == '#' )
return validHexColorString( str );
if ( searchColorNames ) {
String::toLowerInPlace( str );
initColorMap();
auto it = sColorMap.find( String::hash( str ) );
if ( it != sColorMap.end() )
return true;
}
if ( String::istartsWith( str, "rgb(" ) )
return true;
else if ( String::istartsWith( str, "rgba(" ) )
return true;
else if ( String::istartsWith( str, "hsl(" ) )
return true;
else if ( String::istartsWith( str, "hsla(" ) )
return true;
else if ( String::istartsWith( str, "hsv(" ) )
return true;
else if ( String::istartsWith( str, "hsva(" ) )
return true;
else if ( String::istartsWith( str, "@color/" ) )
return true;
else if ( sColors.find( str ) != sColors.end() )
return true;
return false;
}
bool Color::isColorString( String::View str, bool searchColorNames ) {
template <AllowedFunctionString StringType>
bool Color::isColorStringT( StringType str, bool searchColorNames ) {
if ( str.empty() )
return false;
@@ -759,43 +726,94 @@ bool Color::isColorString( String::View str, bool searchColorNames ) {
if ( searchColorNames && str.size() <= 32 ) {
initColorMap();
String::HashType hash = 5381;
for ( size_t i = 0; i < str.size(); ++i )
hash = ( ( hash << 5 ) + hash ) + std::tolower( str[i] );
auto it = sColorMap.find( hash );
if ( it != sColorMap.end() )
String::HashType hash = String::hashToLower( str );
if ( sColorMap.find( hash ) != sColorMap.end() )
return true;
std::string lowerStr( String( str ).toUtf8() );
String::toLowerInPlace( lowerStr );
if ( sColors.find( lowerStr ) != sColors.end() )
if ( sColorHash.find( hash ) != sColorHash.end() )
return true;
}
if ( String::istartsWith( str, "rgb(" ) )
return true;
else if ( String::istartsWith( str, "rgba(" ) )
return true;
else if ( String::istartsWith( str, "hsl(" ) )
return true;
else if ( String::istartsWith( str, "hsla(" ) )
return true;
else if ( String::istartsWith( str, "hsv(" ) )
return true;
else if ( String::istartsWith( str, "hsva(" ) )
return true;
else if ( String::istartsWith( str, "@color/" ) )
return true;
if ( String::istartsWith( str, "@color/" ) ) {
std::string utf8Str;
if constexpr ( std::is_same_v<StringType, String::View> ) {
if ( LuaPattern::hasMatches( String( str ).toUtf8(), "@color/[%w_][%w_-]+" ) ) {
return true;
}
} else {
if ( LuaPattern::hasMatches( str, "@color/[%w_][%w_-]+" ) ) {
return true;
}
}
}
if ( str.back() == ')' ) {
FunctionString func = FunctionString::parse( str );
if ( !func.isEmpty() ) {
std::string name = func.getName();
String::toLowerInPlace( name );
if ( name == "rgb" || name == "rgba" || name == "hsl" || name == "hsla" ||
name == "hsv" || name == "hsva" ) {
const auto& params = func.getParameters();
if ( params.empty() || params.size() > 4 )
return false;
for ( const auto& param : params ) {
if ( param.empty() )
return false;
bool hasFunc = false;
static const char* allowedFuncs[] = {
"var(", "calc(", "min(", "max(", "clamp(", "env(", "color-mix(", "color(" };
for ( const char* f : allowedFuncs ) {
if ( param.find( f ) != std::string::npos ) {
hasFunc = true;
break;
}
}
if ( hasFunc )
continue;
for ( auto c : param ) {
if ( !( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) ||
( c >= '0' && c <= '9' ) || c == '.' || c == '%' || c == '-' ||
c == '+' || c == ' ' || c == '/' ) ) {
return false;
}
}
}
return true;
}
}
}
return false;
}
bool Color::isColorString( std::string_view str, bool searchColorNames ) {
return isColorStringT<std::string_view>( str, searchColorNames );
}
bool Color::isColorString( String::View str, bool searchColorNames ) {
return isColorStringT<String::View>( str, searchColorNames );
}
void Color::registerColor( const std::string& name, const Color& color ) {
sColors[String::toLower( name )] = color;
std::string lowerName( String::toLower( name ) );
sColors[lowerName] = color;
sColorHash[String::hash( lowerName )] = color;
}
bool Color::unregisterColor( const std::string& name ) {
return sColors.erase( String::toLower( name ) ) > 0;
std::string lowerName( String::toLower( name ) );
sColorHash.erase( String::hash( lowerName ) );
return sColors.erase( lowerName ) > 0;
}
bool Color::validHexColorString( String::View hexColor ) {
+60 -29
View File
@@ -4,32 +4,54 @@
namespace EE { namespace System {
FunctionString FunctionString::parse( const std::string& function ) {
#include <concepts>
#include <string>
template <AllowedFunctionString StringType>
FunctionString FunctionString::parse( StringType function ) {
using CharType = typename StringType::value_type;
size_t funcSep = function.find( '(' );
if ( funcSep == std::string::npos )
if ( funcSep == StringType::npos )
return FunctionString( "", {}, {} );
std::string funcName = function.substr( 0, funcSep );
String::trimInPlace( funcName );
auto funcName = String::trim( function.substr( 0, funcSep ) );
Parameters funcParameters;
TypeStringVector typeStringData;
std::vector<std::string> funcParameters;
std::vector<bool> typeStringData;
std::string parametersString = function.substr( funcSep + 1 );
auto parametersString = function.substr( funcSep + 1 );
size_t paramClose = parametersString.find_last_of( ')' );
if ( paramClose == std::string::npos )
if ( paramClose == StringType::npos )
return FunctionString( "", {}, {} );
parametersString = parametersString.substr( 0, paramClose );
bool stateParsingString = false;
std::string buffer = "";
char prevChar = 0;
std::basic_string<CharType> buffer;
CharType prevChar = 0;
bool currentParamIsString = false;
int parenDepth = 0;
auto pushBufferToParams = [&]() {
if constexpr ( std::same_as<CharType, char> ) {
if ( !currentParamIsString )
String::trimInPlace( buffer );
funcParameters.push_back( buffer );
} else {
std::string utf8Buffer = String( buffer ).toUtf8();
if ( !currentParamIsString )
String::trimInPlace( utf8Buffer );
funcParameters.push_back( utf8Buffer );
}
typeStringData.push_back( currentParamIsString );
buffer.clear();
currentParamIsString = false;
};
for ( size_t i = 0; i < parametersString.length(); ++i ) {
char c = parametersString[i];
CharType c = parametersString[i];
if ( !stateParsingString ) {
if ( c == '(' ) {
@@ -37,19 +59,14 @@ FunctionString FunctionString::parse( const std::string& function ) {
buffer += c;
} else if ( c == ')' ) {
if ( parenDepth == 0 )
break; // early exit, last ) wasn't the function closure
break;
if ( parenDepth > 0 )
parenDepth--;
buffer += c;
} else if ( c == ',' ) {
if ( parenDepth == 0 ) {
if ( !buffer.empty() ) {
if ( !currentParamIsString )
String::trimInPlace( buffer );
funcParameters.push_back( buffer );
typeStringData.push_back( currentParamIsString );
buffer = "";
currentParamIsString = false;
pushBufferToParams();
}
} else {
buffer += c;
@@ -84,25 +101,39 @@ FunctionString FunctionString::parse( const std::string& function ) {
}
}
if ( !buffer.empty() ) {
if ( !currentParamIsString )
String::trimInPlace( buffer );
funcParameters.push_back( buffer );
typeStringData.push_back( currentParamIsString );
}
if ( !buffer.empty() )
pushBufferToParams();
return FunctionString( funcName, funcParameters, typeStringData );
if constexpr ( std::same_as<StringType, std::string> ) {
return FunctionString( std::string{ funcName }, funcParameters, typeStringData );
} else {
return FunctionString( String( funcName ).toUtf8(), funcParameters, typeStringData );
}
}
FunctionString::FunctionString( const std::string& name, const std::vector<std::string>& parameters,
const std::vector<bool>& typeStringData ) :
FunctionString FunctionString::parse( std::string_view function ) {
return parse<std::string_view>( function );
}
FunctionString FunctionString::parse( String::View function ) {
return parse<String::View>( function );
}
FunctionString::FunctionString( const std::string& name, const Parameters& parameters,
const TypeStringVector& typeStringData ) :
name( name ), parameters( parameters ), typeStringData( typeStringData ) {}
FunctionString::FunctionString( const std::string& name, Parameters&& parameters,
TypeStringVector&& typeStringData ) :
name( name ),
parameters( std::move( parameters ) ),
typeStringData( std::move( typeStringData ) ) {}
const std::string& FunctionString::getName() const {
return name;
}
const std::vector<std::string>& FunctionString::getParameters() const {
const FunctionString::Parameters& FunctionString::getParameters() const {
return parameters;
}
+7 -8
View File
@@ -35,16 +35,16 @@ std::string_view LuaPattern::getURIPattern() {
return "%w+://[%w_.~!*:@&+$/?%%#-]-%w[-.%w]*%.%w%w%w?%w?:?%d*/?[%w_.~!*:@&+$/?%%#=-]*"sv;
}
std::string LuaPattern::match( const std::string& string, const std::string_view& pattern ) {
std::string LuaPattern::match( std::string_view string, std::string_view pattern ) {
LuaPattern matcher( pattern );
int start = 0, end = 0;
if ( matcher.find( string, start, end ) )
return string.substr( start, end - start );
if ( matcher.find( string.data(), start, end, 0, string.size() ) )
return std::string{ string.substr( start, end - start ) };
return "";
}
std::string LuaPattern::matchesAny( const std::vector<std::string>& stringvec,
const std::string_view& pattern ) {
std::string_view pattern ) {
LuaPattern matcher( pattern );
int start = 0, end = 0;
for ( const auto& str : stringvec ) {
@@ -55,16 +55,15 @@ std::string LuaPattern::matchesAny( const std::vector<std::string>& stringvec,
return "";
}
PatternMatcher::Range LuaPattern::firstMatch( const std::string& string,
const std::string_view& pattern ) {
PatternMatcher::Range LuaPattern::firstMatch( std::string_view string, std::string_view pattern ) {
LuaPattern matcher( pattern );
int start = 0, end = 0;
if ( matcher.find( string, start, end ) )
if ( matcher.find( string.data(), start, end, 0, string.size() ) )
return { start, end };
return { -1, -1 };
}
bool LuaPattern::hasMatches( const std::string& string, const std::string_view& pattern ) {
bool LuaPattern::hasMatches( std::string_view string, std::string_view pattern ) {
return LuaPattern::firstMatch( string, pattern ).isValid();
}
+5 -5
View File
@@ -66,7 +66,7 @@ void DrawableImageParser::registerBaseParsers() {
RectangleDrawable* drawable = RectangleDrawable::New();
RectColors rectColors;
const std::vector<std::string>& params( functionType.getParameters() );
const auto& params( functionType.getParameters() );
if ( Color::isColorString( params.at( 0 ) ) && params.size() >= 2 ) {
rectColors.TopLeft = rectColors.TopRight = Color::fromString( params.at( 0 ) );
@@ -112,7 +112,7 @@ void DrawableImageParser::registerBaseParsers() {
CircleDrawable* drawable = CircleDrawable::New();
const std::vector<std::string>& params( functionType.getParameters() );
const auto& params( functionType.getParameters() );
CSS::StyleSheetLength length( params[0] );
drawable->setRadius( node->convertLength( length, size.getWidth() / 2.f ) );
@@ -145,7 +145,7 @@ void DrawableImageParser::registerBaseParsers() {
RectColors rectColors;
std::vector<Color> colors;
const std::vector<std::string>& params( functionType.getParameters() );
const auto& params( functionType.getParameters() );
for ( size_t i = 0; i < params.size(); i++ ) {
std::string param( String::toLower( params[i] ) );
@@ -207,7 +207,7 @@ void DrawableImageParser::registerBaseParsers() {
std::vector<Color> colors;
std::vector<Vector2f> vertices;
const std::vector<std::string>& params( functionType.getParameters() );
const auto& params( functionType.getParameters() );
Float lineWidth = PixelDensity::dpToPx( 1.f );
for ( size_t i = 0; i < params.size(); i++ ) {
@@ -277,7 +277,7 @@ void DrawableImageParser::registerBaseParsers() {
std::vector<Color> colors;
std::vector<Vector2f> vertices;
const std::vector<std::string>& params( functionType.getParameters() );
const auto& params( functionType.getParameters() );
Float lineWidth = PixelDensity::dpToPx( 1.f );
for ( size_t i = 0; i < params.size(); i++ ) {
+3 -3
View File
@@ -662,14 +662,14 @@ void TextDocument::guessIndentType() {
int guessCountdown = 10;
for ( size_t i = start; i < end; i++ ) {
const String& text = mLines[i].getText();
std::string match =
LuaPattern::match( text.size() > 128 ? text.substr( 0, 12 ) : text, "^ +" );
std::string match = LuaPattern::match(
text.size() > 128 ? text.substr( 0, 128 ).toUtf8() : text.toUtf8(), "^ +" );
if ( !match.empty() ) {
guessSpaces++;
guessWidth[match.size()]++;
guessCountdown--;
} else {
match = LuaPattern::match( mLines[i].getText(), "^\t+" );
match = LuaPattern::match( mLines[i].getText().toUtf8(), "^\t+" );
if ( !match.empty() ) {
guessTabs++;
guessCountdown--;
+8
View File
@@ -312,6 +312,10 @@ void UINode::setMaxSizeEq( const std::string& maxWidthEq, const std::string& max
if ( mMaxWidthEq != maxWidthEq || mMaxHeightEq != maxHeightEq ) {
mMaxWidthEq = maxWidthEq;
mMaxHeightEq = maxHeightEq;
if ( mMaxWidthEq == "none" )
mMaxWidthEq.clear();
if ( mMaxHeightEq == "none" )
mMaxHeightEq.clear();
setSize( mDpSize );
}
}
@@ -319,6 +323,8 @@ void UINode::setMaxSizeEq( const std::string& maxWidthEq, const std::string& max
void UINode::setMaxWidthEq( const std::string& maxWidthEq ) {
if ( mMaxWidthEq != maxWidthEq ) {
mMaxWidthEq = maxWidthEq;
if ( mMaxWidthEq == "none" )
mMaxWidthEq.clear();
onSizeChange();
}
}
@@ -330,6 +336,8 @@ const std::string& UINode::getMaxHeightEq() const {
void UINode::setMaxHeightEq( const std::string& maxHeightEq ) {
if ( mMaxHeightEq != maxHeightEq ) {
mMaxHeightEq = maxHeightEq;
if ( mMaxHeightEq == "none" )
mMaxHeightEq.clear();
onSizeChange();
}
}
+6 -2
View File
@@ -17,9 +17,9 @@ namespace EE { namespace UI {
class UILineBreak : public UIRichText {
public:
static UILineBreak* New() { return eeNew( UILineBreak, () ); }
static UILineBreak* New( const std::string& tag = "" ) { return eeNew( UILineBreak, ( tag ) ); }
UILineBreak() : UIRichText( "br " ) {}
UILineBreak( const std::string& tag = "br" ) : UIRichText( tag ) {}
virtual Uint32 getType() const { return UI_TYPE_BR; }
@@ -32,6 +32,10 @@ UIRichText* UIRichText::NewBr() {
return UILineBreak::New();
};
UIRichText* UIRichText::NewHr() {
return UILineBreak::New( "hr" );
};
UIRichText* UIRichText::New() {
return eeNew( UIRichText, () );
}
+1
View File
@@ -155,6 +155,7 @@ void UIWidgetCreator::createBaseWidgetList() {
registeredWidget["h5"] = UIRichText::NewH5;
registeredWidget["h6"] = UIRichText::NewH6;
registeredWidget["br"] = UIRichText::NewBr;
registeredWidget["hr"] = UIRichText::NewHr;
registeredWidget["ul"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ul" ); };
registeredWidget["ol"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ol" ); };
registeredWidget["li"] = UIRichText::NewListItem;
+22 -1
View File
@@ -14,6 +14,9 @@ EE_MAIN_FUNC int main( int argc, char** argv ) {
{ 'c', "prefers-color-scheme" } );
args::Flag hnDark( parser, "hn-dark",
"Force a custom CSS style for Hacker News site to be dark.", { "hn-dark" } );
args::Flag benchmarkMode( parser, "benchmark-mode",
"Render as much as possible to measure the rendering performance.",
{ "benchmark-mode" } );
try {
parser.ParseCLI( Sys::parseArguments( argc, argv ) );
@@ -30,7 +33,10 @@ EE_MAIN_FUNC int main( int argc, char** argv ) {
return EXIT_FAILURE;
}
UIApplication app( { 1280, 720, "eepp - UI HTML Example" } );
UIApplication app(
{ 1280, 720, "eepp - UI HTML Example" }, UIApplication::Settings(),
ContextSettings(
false, benchmarkMode.Get() ? 0 : ContextSettings::FrameRateLimitScreenRefreshRate ) );
Log::instance()->setLogLevelThreshold( LogLevel::Debug );
Log::instance()->setLogToStdOut( true );
@@ -223,5 +229,20 @@ EE_MAIN_FUNC int main( int argc, char** argv ) {
}
} );
if ( benchmarkMode.Get() ) {
app.getWindow()->runMainLoop( [&app]() {
app.getWindow()->getInput()->update();
SceneManager::instance()->update();
app.getWindow()->clear();
SceneManager::instance()->draw();
auto tm = app.getUI()->getUIThemeManager();
String fps( String::format( "FPS: %d", app.getWindow()->getFPS() ) );
Text::draw( fps, Vector2f::Zero, tm->getDefaultFont(), tm->getDefaultFontSize(),
Color::magenta, 0, 0, Color::Black, Color::Black, Vector2f{ 1, 1 }, 4,
TextHints::AllAscii );
app.getWindow()->display();
} );
return EXIT_SUCCESS;
}
return app.run();
}