mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Fix ex and ch units.
This commit is contained in:
@@ -6,6 +6,10 @@
|
||||
#include <eepp/scene/scenenode.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace EE { namespace Graphics {
|
||||
class Font;
|
||||
}} // namespace EE::Graphics
|
||||
|
||||
using namespace EE::Math;
|
||||
|
||||
namespace EE { namespace UI { namespace CSS {
|
||||
@@ -62,10 +66,12 @@ class EE_API StyleSheetLength {
|
||||
const Unit& getUnit() const;
|
||||
|
||||
Float asPixels( const Float& parentSize, const Sizef& viewSize, const Float& displayDpi,
|
||||
const Float& elFontSize = 12, const Float& globalFontSize = 12 ) const;
|
||||
const Float& elFontSize = 12, const Float& globalFontSize = 12,
|
||||
Graphics::Font* font = nullptr ) const;
|
||||
|
||||
Float asDp( const Float& parentSize, const Sizef& viewSize, const Float& displayDpi,
|
||||
const Float& elFontSize = 12, const Float& globalFontSize = 12 ) const;
|
||||
const Float& elFontSize = 12, const Float& globalFontSize = 12,
|
||||
Graphics::Font* font = nullptr ) const;
|
||||
|
||||
bool operator==( const StyleSheetLength& val ) const;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <eepp/core/string.hpp>
|
||||
#include <eepp/graphics/font.hpp>
|
||||
#include <eepp/graphics/pixeldensity.hpp>
|
||||
#include <eepp/math/math.hpp>
|
||||
#include <eepp/system/luapattern.hpp>
|
||||
@@ -220,7 +221,7 @@ const StyleSheetLength::Unit& StyleSheetLength::getUnit() const {
|
||||
|
||||
Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize,
|
||||
const Float& displayDpi, const Float& elFontSize,
|
||||
const Float& globalFontSize ) const {
|
||||
const Float& globalFontSize, Graphics::Font* font ) const {
|
||||
Float ret = 0;
|
||||
|
||||
// CSS dictates a base 96 DPI for logical pixels.
|
||||
@@ -243,9 +244,29 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize
|
||||
ret = Math::roundUp( PixelDensity::dpToPx( mValue ) );
|
||||
break;
|
||||
case Unit::Em:
|
||||
case Unit::Ch: // Using Em for Ch is incorrect but not that incorrect, close enough
|
||||
ret = Math::round( mValue * elFontSize );
|
||||
break;
|
||||
case Unit::Ex:
|
||||
if ( font && elFontSize > 0 ) {
|
||||
Glyph glyph =
|
||||
font->getGlyph( 'x', static_cast<unsigned int>( elFontSize ), false, false );
|
||||
Float xHeight = eemax( 0.f, -glyph.bounds.Top );
|
||||
if ( xHeight <= 0 )
|
||||
xHeight = elFontSize * 0.5f;
|
||||
ret = Math::round( mValue * xHeight );
|
||||
} else {
|
||||
ret = Math::round( mValue * elFontSize * 0.5f );
|
||||
}
|
||||
break;
|
||||
case Unit::Ch:
|
||||
if ( font && elFontSize > 0 ) {
|
||||
Glyph glyph =
|
||||
font->getGlyph( '0', static_cast<unsigned int>( elFontSize ), false, false );
|
||||
ret = Math::round( mValue * eemax( 0.f, glyph.advance ) );
|
||||
} else {
|
||||
ret = Math::round( mValue * elFontSize * 0.5f );
|
||||
}
|
||||
break;
|
||||
case Unit::Pt:
|
||||
ret = mValue * CSS_DPI / 72.f;
|
||||
break;
|
||||
@@ -290,9 +311,9 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize
|
||||
|
||||
Float StyleSheetLength::asDp( const Float& parentSize, const Sizef& viewSize,
|
||||
const Float& displayDpi, const Float& elFontSize,
|
||||
const Float& globalFontSize ) const {
|
||||
const Float& globalFontSize, Graphics::Font* font ) const {
|
||||
return PixelDensity::pxToDp(
|
||||
asPixels( parentSize, viewSize, displayDpi, elFontSize, globalFontSize ) );
|
||||
asPixels( parentSize, viewSize, displayDpi, elFontSize, globalFontSize, font ) );
|
||||
}
|
||||
|
||||
bool StyleSheetLength::operator==( const StyleSheetLength& length ) const {
|
||||
|
||||
@@ -1796,12 +1796,19 @@ Float UINode::convertLength( const CSS::StyleSheetLength& length,
|
||||
} else {
|
||||
rootFontSize = getAbsoluteFontSize( getUISceneNode()->getRoot() );
|
||||
}
|
||||
} else if ( length.getUnit() == StyleSheetLength::Unit::Em && isWidget() ) {
|
||||
} else if ( ( length.getUnit() == StyleSheetLength::Unit::Em ||
|
||||
length.getUnit() == StyleSheetLength::Unit::Ex ||
|
||||
length.getUnit() == StyleSheetLength::Unit::Ch ) &&
|
||||
isWidget() ) {
|
||||
elFontSize = getAbsoluteFontSize( asConstType<UIWidget>() );
|
||||
}
|
||||
|
||||
Graphics::Font* font = nullptr;
|
||||
if ( getUISceneNode() && getUISceneNode()->getUIThemeManager() )
|
||||
font = getUISceneNode()->getUIThemeManager()->getDefaultFont();
|
||||
|
||||
auto ret = length.asPixels( containerLength, getSceneNode()->getPixelsSize(),
|
||||
getSceneNode()->getDPI(), elFontSize, rootFontSize );
|
||||
getSceneNode()->getDPI(), elFontSize, rootFontSize, font );
|
||||
|
||||
if ( ( mFlags & UI_HTML_ELEMENT ) && length.getUnit() == StyleSheetLength::Unit::Px )
|
||||
ret = PixelDensity::dpToPx( ret ); // scale px as if where dp in HTML elements
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "utest.hpp"
|
||||
#include <eepp/graphics/font.hpp>
|
||||
#include <eepp/graphics/fontmanager.hpp>
|
||||
#include <eepp/scene/node.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/ui/css/stylesheet.hpp>
|
||||
#include <eepp/ui/css/stylesheetlength.hpp>
|
||||
#include <eepp/ui/css/stylesheetproperty.hpp>
|
||||
#include <eepp/ui/css/stylesheetspecification.hpp>
|
||||
#include <eepp/ui/uiapplication.hpp>
|
||||
@@ -11,12 +13,14 @@
|
||||
#include <eepp/ui/uistyle.hpp>
|
||||
#include <eepp/ui/uitextspan.hpp>
|
||||
#include <eepp/ui/uitextview.hpp>
|
||||
#include <eepp/ui/uithememanager.hpp>
|
||||
#include <eepp/ui/uiwidget.hpp>
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::UI;
|
||||
using namespace EE::UI::CSS;
|
||||
using namespace EE::Scene;
|
||||
using namespace EE::Graphics;
|
||||
|
||||
UTEST( CSSInheritance, HtmlXmlLoadingInheritance ) {
|
||||
UIApplication app(
|
||||
@@ -331,3 +335,88 @@ UTEST( CSSInheritance, ExplicitBackgroundColorInherit ) {
|
||||
|
||||
EXPECT_TRUE( Color( "#00FF00" ) == child->getBackgroundColor() );
|
||||
}
|
||||
|
||||
UTEST( CSSUnits, ExFallback ) {
|
||||
StyleSheetLength len( "100ex" );
|
||||
Float result = len.asPixels( 0, Sizef::Zero, 96, 16, 16 );
|
||||
EXPECT_EQ( Math::round( 100.f * 16.f * 0.5f ), result );
|
||||
}
|
||||
|
||||
UTEST( CSSUnits, ChFallback ) {
|
||||
StyleSheetLength len( "100ch" );
|
||||
Float result = len.asPixels( 0, Sizef::Zero, 96, 16, 16 );
|
||||
EXPECT_EQ( Math::round( 100.f * 16.f * 0.5f ), result );
|
||||
}
|
||||
|
||||
UTEST( CSSUnits, ExChWithFont ) {
|
||||
UIApplication app(
|
||||
WindowSettings( 800, 600, "eepp - CSS Units Ex/Ch Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32 ),
|
||||
UIApplication::Settings( Sys::getProcessPath() + ".." + FileSystem::getOSSlash() ), 1.f );
|
||||
|
||||
Graphics::Font* font =
|
||||
app.getUI()->getUIThemeManager()->getDefaultFont();
|
||||
EXPECT_TRUE( font != nullptr );
|
||||
|
||||
Float elFontSize = 24.f;
|
||||
|
||||
Float resultEx = StyleSheetLength( "1ex" ).asPixels( 0, Sizef::Zero, 96, elFontSize, 16, font );
|
||||
Float resultCh = StyleSheetLength( "1ch" ).asPixels( 0, Sizef::Zero, 96, elFontSize, 16, font );
|
||||
Float resultEm = StyleSheetLength( "1em" ).asPixels( 0, Sizef::Zero, 96, elFontSize, 16, font );
|
||||
Float fallback = Math::round( elFontSize * 0.5f );
|
||||
|
||||
EXPECT_GT( resultEx, 0.f );
|
||||
EXPECT_GT( resultCh, 0.f );
|
||||
EXPECT_EQ( elFontSize, resultEm );
|
||||
EXPECT_LE( resultEx, resultEm );
|
||||
EXPECT_LE( resultCh, resultEm );
|
||||
EXPECT_NE( fallback, resultEx );
|
||||
EXPECT_NE( fallback, resultCh );
|
||||
}
|
||||
|
||||
UTEST( CSSUnits, Integration ) {
|
||||
for ( Float scale : { 1.f, 1.5f, 2.f } ) {
|
||||
UTEST_PRINT_STEP( String::format( "SCALE %.1f", scale ).c_str() );
|
||||
UIApplication app( WindowSettings( 800, 600, "eepp - CSS Units Ex/Ch Integration Test",
|
||||
WindowStyle::Default, WindowBackend::Default, 32 ),
|
||||
UIApplication::Settings(
|
||||
Sys::getProcessPath() + ".." + FileSystem::getOSSlash(), scale ) );
|
||||
|
||||
std::string xml = R"(
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.text {
|
||||
font-size: 20px;
|
||||
}
|
||||
#exbox {
|
||||
width: 10ex;
|
||||
height: 2ex;
|
||||
}
|
||||
#chbox {
|
||||
width: 10ch;
|
||||
height: 2ch;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="exbox" class="text">x</div>
|
||||
<div id="chbox" class="text">0</div>
|
||||
</body>
|
||||
</html>
|
||||
)";
|
||||
|
||||
UIWidget* root = app.getUI()->loadLayoutFromString( xml );
|
||||
EXPECT_TRUE( root != nullptr );
|
||||
|
||||
UIRichText* exbox = root->querySelector( "#exbox" )->asType<UIRichText>();
|
||||
EXPECT_TRUE( exbox != nullptr );
|
||||
EXPECT_GT( exbox->getPixelsSize().getWidth(), 0.f );
|
||||
EXPECT_GT( exbox->getPixelsSize().getHeight(), 0.f );
|
||||
|
||||
UIRichText* chbox = root->querySelector( "#chbox" )->asType<UIRichText>();
|
||||
EXPECT_TRUE( chbox != nullptr );
|
||||
EXPECT_GT( chbox->getPixelsSize().getWidth(), 0.f );
|
||||
EXPECT_GT( chbox->getPixelsSize().getHeight(), 0.f );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user