From 7c2fad64bc972c1910b514f6c4d979d5204cc26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Tue, 28 Apr 2026 01:14:04 -0300 Subject: [PATCH] Add `font` shorthand parser (a simplified version to what we can support now). --- .../assets/html/eepp-ui-anchor-margins.webp | Bin 1586 -> 1478 bytes .../assets/html/eepp-ui-span-padding.webp | Bin 4764 -> 6372 bytes include/eepp/ui/css/shorthanddefinition.hpp | 3 +- src/eepp/ui/css/shorthanddefinition.cpp | 2 +- src/eepp/ui/css/stylesheetspecification.cpp | 148 ++++++++++++++++++ 5 files changed, 151 insertions(+), 2 deletions(-) diff --git a/bin/unit_tests/assets/html/eepp-ui-anchor-margins.webp b/bin/unit_tests/assets/html/eepp-ui-anchor-margins.webp index 70f198101918eb6a2a6dde1a281648026607cb89..e8e35dabb695385abc3f5e126d90113df2528bf0 100644 GIT binary patch literal 1478 zcmdUt`!^E`0LK+dZ^^CDHF+#5EssTwJ27F&V;!&7=6E&H>ac`6d5ye@ZJ5csP$Fsb zUb(8FwQNH2W-Q4zl5M)S>)!j*{S)pv-*dj--@c#oJzs>=g$oR21qCmATQ^TPOXtST z3<7kM6(;A(u=-Bvp#?n%>zTwV8 zi`R9(X0ERipWqO$cG%mf%u?_^cuFzViDFehFE#P>);tZ4GAosE!X_zA<&DnX zgYoVpT@?uulDHLaXycRwbgZ6pdK zSB>ZbGAK>ibTGqLVzs|;y=#MZybb^%Mpp3ZUU@zoAh=hy-3uFs7r6p}CsC??)4cSU zld-3NcVais|1#*!F!!4!@rrBmzS+*c&9cVUpBvG-oEFt>CmwmmZ1h5K28x^cUyO2nR|E0 zXj&E^4%@Ewo@Rw@fFx(w3+`w1rTU-jPHphtYGK*Q$;;^k1J6*{P2;?aVu~a>P14pcZ-!R z6&K?$!uiH~(18Vb+r1NyPEB{h2-2<^_T!ZZJ<^S3=4>d@baa&*jE zEWIaciTjSEDiCQu9YNve(e%{=z5n4G(=rdf&t$mlk+vL4;z|!b#QXFWQiio;&aUp< zOHy{-p9M8-PE~=B%dt0gG#sf?a!yUXo8E8bG(L6R+gME?;ZKh;KsrUC(ciSHBK9`d zsBz@h*K14wm$L_mm`>ExZqV7Xh+&uNACWiRDwSqwvtFs2i=llvtpZxVtA0}-EBr!0 zc!ckPB{aFD;9`f~uLk}X@#C>)g8R$XHditx-8g|OcuTAgA=*>?oI z>=E+z7>#v9IR>wMiBx7@(7?1dZDs_!<<~e*CHI9P;!0)1OEM#E<9A=G2i76OwOf#Z z9czoF3p>`QyF2RtY2Ox<9e;Iv7&h@l?e%la694-7Q_OtlF~67~1C)%vjE{jsGZ$P* zKX9)+q2ST_+V9b=2}m69ZcGD^j#-+Ge%^U(3Y93OE(+f8*@cF<6y!%&jdx#AZ|jUC zpI{L7^w`)(Y_yBs1Luc7ULGo?5skmo3PhB!UCiEYY76p=9>*4%%Q|l6Fw;vis(k%b z23$dtb&Nshe6$dR7Yy(DG4P`*YA%v4PQ=)kccuq(LHs^50C<$xa`$O+0@YqHI}tLI za?2lMW{)q8cU5;b_lk(-&AaSxRaCl`8=$eFh?E7yo#1Ah<$^etjPvIx@WsiEES#t{ zh;irZy01Leg_vT&S;X}o{r4O={X!|xdwfz~g!ZVd4qw4?DIYvnfrITs^_uwXLmsbz sgG^5h86$LTxPK|cN?Xz}VJZ)`Dj{j+Y?l$_Q&7pi|E+yJ?6^hYFHoQx<^TWy literal 1586 zcmd6k>pK$)0LF(YmmG2_OL7h2xRV;@GP5n5A=6r^R+zCuRBq)G<~D3eJZ5XAt8|%G zD!Ig(ax0f;qleIrLkKg59i6}8JkR^#{rJAWUmyYoGv5XPgm`A9Pc(+duJByiO(Bcc`eysu3RXsbNYXRh zx09ghhGq<4VYdWl1owcNY3^50LwG2uDZTS;EtpEPJM6Jnm1JWS=MXb1XOD#CG>FoM zrqq;gvt4bf6%X%-R{f-aqR8gunrR0L<_-Wgy?W1RdtWbS6nlEP17!eAWgx8}t$a4X z-_Fcl{(!oz20BlFlb{>XX}e$6ftB_}>J!k*QK8P~jJV2D4RNw?YJ+d^Pu)b^F1KdX z5N9@;H9La1TZtn!+DGv@#NQF=BfbTLhaq1Q>30*sRl^%^Nt@s}K8(^oa&a$DG_xqj zCF&fSZi*qUojeD%iRL@0oAxd@X`$v~*XJM;hUaPuv13TmsfU^x0}6VRlN@@CZ=Zmg zdw;TZDB{<5<_xq}+jrn&xYoYEPZ)qw-mn0R$?eACrSxYG`u>y=*;L+ks$5;?qPetQ<8;r zA97+4+#4aFt%fO=9G~Z|z4`1)q`CnZuZnJ7eIm*^dM3Ea%jE=CeAN=#F&%G@Vh4ii zU7~i8QK=zZ^3Z{H{NT$($gK1$RNQ0@bV~^O{)}JThEHfod40_DMTmg@NApOnr(Ml+ z=L@d%XbK2cn(H@OF7K{h96-2LIXqPuicuW1Y_6Pe=}g*DdFtnIeTc^NAai%POGwp; z8+ys>`+^@NK9k#%5Lfi0<>@8MZY86nNOlFRG$M8vZqSGnSfk}=QQDHV4703Vt1Hm0 zwv_SP_O@o@v49-#mz8_Ua!hwyt}(Y=cXU2daU`_bADH$UlXVUWW_OV)Z^mbPgyE={ z!)1zr=WgsVBu7?opvD6V+M6zZ09ue+yuUu>gIAGiMXUXx7u~r#oK-y9dU82=^t%E^4$Dr~w2EMf?m&IgwZ1FLR$h6uudySVGO~Y#6x_Ujq z#NRlURj+6R^?dP#+yrPIsEx$4Q04unJGzQLw3%E`4mw0P$dEwOf*tkrIW<4Nh*QPW4lKYM6B41PO0D_D67_DPL0N~M%O6^b*X&VmJbyymCG|s7}foj ziY7X;@94jv)CPb90=u-rtF$s-g`~foHp@-tVUYGfu}3 zA>3j2&t!P<8%y#(UWth;FX4MHe!uj!Vn6oB`C>ff!@<^$t6VEZ1JHdQ!1~UcL2+m= z-v%AJeIQ{_yX2uxf7>fF3@C<3+evt^WuBIIyz?en$Bo0>I6K^zz`M3dE;>>P$DJ6( zT_?kZqC5mWJ1I_yS9`uC>k&-+WFj0MhEtuFY%~yB2(oraKdP{V@)+9)!l!m@K7&#@ zkC1O@>!2b0H!kjKmg| zL3L~7_vZtdn(RfLGVznwj(w1A&Y5W;+mGGTAU1UEm$b9gg(4;2WWyt5D&}P0THtuQ z;eYObUi|zX@%*%-3>ZmVf~-zUgqUNt8vR;*OYBwE^zOCM$yjLpe bdBLM66;*pQzF%mP&g)4R{_iny00904;zKW} diff --git a/bin/unit_tests/assets/html/eepp-ui-span-padding.webp b/bin/unit_tests/assets/html/eepp-ui-span-padding.webp index 6ddf9b8fb73b409757fb9236e6e70cb929bebbef..63545e563b303ac1cc3815c2ea69609da2e1e5e6 100644 GIT binary patch literal 6372 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 diff --git a/include/eepp/ui/css/shorthanddefinition.hpp b/include/eepp/ui/css/shorthanddefinition.hpp index 4a283d587..e97de7db7 100644 --- a/include/eepp/ui/css/shorthanddefinition.hpp +++ b/include/eepp/ui/css/shorthanddefinition.hpp @@ -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( const ShorthandDefinition* shorthand, diff --git a/src/eepp/ui/css/shorthanddefinition.cpp b/src/eepp/ui/css/shorthanddefinition.cpp index 3331756db..49d507a0c 100644 --- a/src/eepp/ui/css/shorthanddefinition.cpp +++ b/src/eepp/ui/css/shorthanddefinition.cpp @@ -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, "" ); diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp index 5aec8e9ba..5cf4ee98d 100644 --- a/src/eepp/ui/css/stylesheetspecification.cpp +++ b/src/eepp/ui/css/stylesheetspecification.cpp @@ -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 { + 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 properties; + const std::vector& 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 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