Add font shorthand parser (a simplified version to what we can support now).

This commit is contained in:
Martín Lucas Golini
2026-04-28 01:14:04 -03:00
parent f6e284c6f5
commit 7c2fad64bc
5 changed files with 151 additions and 2 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -24,7 +24,8 @@ enum class ShorthandId : Uint32 {
BorderWidth = String::hash( "border-width" ),
BorderRadius = String::hash( "border-radius" ),
MinSize = String::hash( "min-size" ),
MaxSize = String::hash( "max-size" )
MaxSize = String::hash( "max-size" ),
Font = String::hash( "font" )
};
typedef std::function<std::vector<StyleSheetProperty>( const ShorthandDefinition* shorthand,

View File

@@ -21,7 +21,7 @@ ShorthandDefinition::ShorthandDefinition( const std::string& name,
mFuncName( shorthandParserName ),
mId( String::hash( name ) ),
mProperties( properties ) {
for ( auto& sep : {"-", "_"} ) {
for ( auto& sep : { "-", "_" } ) {
if ( mName.find( sep ) != std::string::npos ) {
std::string alias( name );
String::replaceAll( alias, sep, "" );

View File

@@ -522,6 +522,8 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerShorthand( "list-style",
{ "list-style-type", "list-style-position", "list-style-image" },
"list-style" );
registerShorthand( "font", { "font-style", "font-size", "line-spacing", "font-family" },
"font" );
}
void StyleSheetSpecification::registerNodeSelector( const std::string& name,
@@ -1175,6 +1177,152 @@ void StyleSheetSpecification::registerDefaultShorthandParsers() {
}
return properties;
};
mShorthandParsers["font"] = []( const ShorthandDefinition* shorthand,
std::string value ) -> std::vector<StyleSheetProperty> {
value = String::trim( value );
if ( value.empty() )
return {};
std::string lowerVal = String::toLower( value );
static const std::string systemFonts[] = { "caption", "icon", "menu",
"message-box", "small-caption", "status-bar" };
for ( const auto& sysFont : systemFonts ) {
if ( lowerVal == sysFont )
return {};
}
std::vector<StyleSheetProperty> properties;
const std::vector<std::string>& propNames = shorthand->getProperties();
int stylePos = getIndexEndingWith( propNames, "-style" );
int sizePos = getIndexEndingWith( propNames, "-size" );
int linePos = getIndexEndingWith( propNames, "-spacing" );
int familyPos = getIndexEndingWith( propNames, "-family" );
static const std::string sizeKeywords[] = {
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "xxx-large" };
auto isSizeKeyword = []( const std::string& t ) {
std::string lt = String::toLower( t );
for ( const auto& kw : sizeKeywords ) {
if ( lt == kw )
return true;
}
return false;
};
auto isStyleWord = []( const std::string& t ) {
std::string lt = String::toLower( t );
return lt == "italic" || lt == "oblique" || lt == "normal";
};
auto isWeightWord = []( const std::string& t ) {
std::string lt = String::toLower( t );
return lt == "bold" || lt == "bolder" || lt == "lighter" || lt == "100" ||
lt == "200" || lt == "300" || lt == "400" || lt == "500" || lt == "600" ||
lt == "700" || lt == "800" || lt == "900";
};
auto isNumberOrLength = []( const std::string& t ) {
if ( t.empty() )
return false;
return ( t[0] >= '0' && t[0] <= '9' ) || t[0] == '.' || t[0] == '-';
};
std::vector<std::string> tokens = String::split( value, " ", "", "(", "\"" );
std::string styleStr;
std::string sizeStr;
std::string lineStr;
std::string familyStr;
bool inLineHeight = false;
for ( size_t i = 0; i < tokens.size(); i++ ) {
std::string tok = tokens[i];
String::trimInPlace( tok );
if ( tok.empty() )
continue;
if ( tok == "/" ) {
inLineHeight = true;
continue;
}
if ( !inLineHeight ) {
size_t slashPos = tok.find( '/' );
if ( slashPos != std::string::npos ) {
if ( slashPos == 0 ) {
lineStr = tok.substr( 1 );
String::trimInPlace( lineStr );
continue;
}
sizeStr = tok.substr( 0, slashPos );
lineStr = tok.substr( slashPos + 1 );
String::trimInPlace( lineStr );
continue;
}
}
if ( inLineHeight ) {
lineStr += ( lineStr.empty() ? "" : " " ) + tok;
inLineHeight = false;
continue;
}
if ( !sizeStr.empty() && familyStr.empty() && !isStyleWord( tok ) &&
!isWeightWord( tok ) ) {
familyStr += ( familyStr.empty() ? "" : " " ) + tok;
continue;
}
if ( isStyleWord( tok ) ) {
std::string lt = String::toLower( tok );
if ( lt != "normal" ) {
if ( !styleStr.empty() )
styleStr += "|";
styleStr += lt;
}
continue;
}
if ( isWeightWord( tok ) ) {
std::string lt = String::toLower( tok );
if ( lt != "normal" ) {
if ( !styleStr.empty() )
styleStr += "|";
styleStr += "bold";
}
continue;
}
if ( sizeStr.empty() && ( isNumberOrLength( tok ) || isSizeKeyword( tok ) ) ) {
sizeStr = tok;
continue;
}
familyStr += ( familyStr.empty() ? "" : " " ) + tok;
}
if ( !sizeStr.empty() ) {
if ( stylePos != -1 && !styleStr.empty() )
properties.emplace_back( StyleSheetProperty( propNames[stylePos], styleStr ) );
if ( sizePos != -1 )
properties.emplace_back( StyleSheetProperty( propNames[sizePos], sizeStr ) );
if ( linePos != -1 && !lineStr.empty() )
properties.emplace_back( StyleSheetProperty( propNames[linePos], lineStr ) );
if ( familyPos != -1 && !familyStr.empty() ) {
String::trimInPlace( familyStr );
if ( familyStr.size() >= 2 &&
( ( familyStr[0] == '"' && familyStr.back() == '"' ) ||
( familyStr[0] == '\'' && familyStr.back() == '\'' ) ) ) {
familyStr = familyStr.substr( 1, familyStr.size() - 2 );
}
properties.emplace_back( StyleSheetProperty( propNames[familyPos], familyStr ) );
}
}
return properties;
};
}
}}} // namespace EE::UI::CSS