diff --git a/bin/unit_tests/assets/html/base.css b/bin/unit_tests/assets/html/base.css
index 39496aec7..ce116e654 100644
--- a/bin/unit_tests/assets/html/base.css
+++ b/bin/unit_tests/assets/html/base.css
@@ -1,8 +1,4 @@
body {
- margin-top: 8px;
- margin-right: 8px;
- margin-bottom: 8px;
- margin-left: 8px;
font-size: 11px;
color: black;
background-color: white;
diff --git a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-2.webp b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-2.webp
index 5808b4cb1..f658020cb 100644
Binary files a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-2.webp and b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-2.webp differ
diff --git a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-3.webp b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-3.webp
index 4c2090c4d..340f7f8ee 100644
Binary files a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-3.webp and b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout-3.webp differ
diff --git a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout.webp b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout.webp
index 122f4cd9a..94304b935 100644
Binary files a/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout.webp and b/bin/unit_tests/assets/html/eepp-uihtmltable-complex-layout.webp differ
diff --git a/include/eepp/graphics/drawablesearcher.hpp b/include/eepp/graphics/drawablesearcher.hpp
index 57d413e6f..81efb4da8 100644
--- a/include/eepp/graphics/drawablesearcher.hpp
+++ b/include/eepp/graphics/drawablesearcher.hpp
@@ -3,12 +3,14 @@
#include
#include
+#include
namespace EE { namespace Graphics {
class EE_API DrawableSearcher {
public:
- static Drawable* searchByName( const std::string& name, bool firstSearchSprite = false );
+ static Drawable* searchByName( const std::string& name, bool firstSearchSprite = false,
+ Network::URI referer = "" );
static Drawable* searchById( const Uint32& id );
diff --git a/include/eepp/network/http.hpp b/include/eepp/network/http.hpp
index d05b74a94..f9c6d22ce 100644
--- a/include/eepp/network/http.hpp
+++ b/include/eepp/network/http.hpp
@@ -115,6 +115,9 @@ class EE_API Http : NonCopyable {
** @return Status code of the response */
Status getStatus() const;
+ /** @return True if the response status is successful (2XX status) */
+ bool isOK() const;
+
/** @brief Get the response status description */
const char* getStatusDescription() const;
diff --git a/include/eepp/ui/css/stylesheetlength.hpp b/include/eepp/ui/css/stylesheetlength.hpp
index 8e8a4b542..a1495a840 100644
--- a/include/eepp/ui/css/stylesheetlength.hpp
+++ b/include/eepp/ui/css/stylesheetlength.hpp
@@ -33,6 +33,7 @@ class EE_API StyleSheetLength {
Dprd,
Dpru,
Dpr,
+ Ch,
};
static Unit unitFromString( std::string unitStr );
diff --git a/include/eepp/ui/uiscenenode.hpp b/include/eepp/ui/uiscenenode.hpp
index 71d73a101..5dc830291 100644
--- a/include/eepp/ui/uiscenenode.hpp
+++ b/include/eepp/ui/uiscenenode.hpp
@@ -715,6 +715,9 @@ class EE_API UISceneNode : public SceneNode {
*/
URI solveRelativePath( URI uri, URI baseURI = {} );
+ /** @return The document referer */
+ URI getReferer() const { return mReferer; };
+
protected:
friend class EE::UI::UIWindow;
friend class EE::UI::UIWidget;
@@ -743,6 +746,7 @@ class EE_API UISceneNode : public SceneNode {
Uint32 mCurOnSizeChangeListener{ 0 };
std::shared_ptr mThreadPool;
URI mURI;
+ URI mReferer;
std::function mURLInterceptorCb;
/**
@@ -957,8 +961,7 @@ class EE_API UISceneNode : public SceneNode {
/** @return The document / scene URI used to resolve paths from a complete URI (with
* path+query+fragment+etc) */
- URI getURIFromURL( const URI& url );
-
+ URI getURIFromURL( const URI& url ) const;
};
}} // namespace EE::UI
diff --git a/src/eepp/graphics/drawablesearcher.cpp b/src/eepp/graphics/drawablesearcher.cpp
index 132a644cd..78f80a80a 100644
--- a/src/eepp/graphics/drawablesearcher.cpp
+++ b/src/eepp/graphics/drawablesearcher.cpp
@@ -107,7 +107,8 @@ static Drawable* parseDataURI( const std::string& name ) {
return drawable;
}
-Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSearchSprite ) {
+Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSearchSprite,
+ Network::URI referer ) {
Drawable* drawable = NULL;
if ( name.size() ) {
@@ -147,12 +148,12 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea
} else if ( String::startsWith( name, "file://" ) ) {
std::string filePath( name.substr( 7 ) );
- #if EE_PLATFORM == EE_PLATFORM_WIN
+#if EE_PLATFORM == EE_PLATFORM_WIN
if ( filePath.size() >= 3 && filePath[0] == '/' && String::isLetter( filePath[1] ) &&
filePath[2] == ':' ) {
filePath = filePath.substr( 1 );
}
- #endif
+#endif
drawable = TextureFactory::instance()->getByName( filePath );
@@ -171,17 +172,25 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea
1, 1, 4, Color::Transparent, false, Texture::ClampMode::ClampToEdge, false,
false, name );
+ std::map headers;
+ if ( !referer.empty() )
+ headers["referer"] = referer.toString();
+
Http::getAsync(
- [texture]( const Http&, Http::Request&, Http::Response& response ) {
- if ( !response.getBody().empty() ) {
+ [texture, name]( const Http&, Http::Request&, Http::Response& response ) {
+ if ( response.isOK() && !response.getBody().empty() ) {
Image image( (const Uint8*)&response.getBody()[0],
response.getBody().size() );
if ( image.getPixels() != NULL )
texture->replace( &image );
+ } else {
+ Log::debug( "DrawableSearcher::searchByName: could not download image: "
+ "%s. Error: %d\n%s",
+ name, response.getStatus(), response.getBody() );
}
},
- URI( name ), Seconds( 5 ) );
+ URI( name ), Seconds( 5 ), {}, headers );
}
drawable = texture;
diff --git a/src/eepp/network/http.cpp b/src/eepp/network/http.cpp
index d2f22400b..bc10ff621 100644
--- a/src/eepp/network/http.cpp
+++ b/src/eepp/network/http.cpp
@@ -469,6 +469,10 @@ Http::Response::Status Http::Response::getStatus() const {
return mStatus;
}
+bool Http::Response::isOK() const {
+ return mStatus >= 200 && mStatus < 300;
+}
+
const char* Http::Response::getStatusDescription() const {
switch ( mStatus ) {
// 2xx: success
diff --git a/src/eepp/ui/css/drawableimageparser.cpp b/src/eepp/ui/css/drawableimageparser.cpp
index 91a89538b..06f852692 100644
--- a/src/eepp/ui/css/drawableimageparser.cpp
+++ b/src/eepp/ui/css/drawableimageparser.cpp
@@ -36,7 +36,8 @@ Drawable* DrawableImageParser::createDrawable( const std::string& value, const S
if ( !functionType.isEmpty() ) {
if ( exists( functionType.getName() ) )
return mFuncs[functionType.getName()]( functionType, size, ownIt, node );
- } else if ( NULL != ( res = DrawableSearcher::searchByName( value ) ) ) {
+ } else if ( NULL != ( res = DrawableSearcher::searchByName(
+ value, false, node->getUISceneNode()->getReferer() ) ) ) {
if ( res->getDrawableType() == Drawable::SPRITE )
ownIt = true;
return res;
@@ -334,7 +335,8 @@ void DrawableImageParser::registerBaseParsers() {
return DrawableSearcher::searchByName(
node->getUISceneNode()
->solveRelativePath( functionType.getParameters().at( 0 ) )
- .toString() );
+ .toString(),
+ false, node->getUISceneNode()->getReferer() );
};
mFuncs["icon"] = []( const FunctionString& functionType, const Sizef& size, bool&,
diff --git a/src/eepp/ui/css/mediaquery.cpp b/src/eepp/ui/css/mediaquery.cpp
index dff7d4182..974a7e92e 100644
--- a/src/eepp/ui/css/mediaquery.cpp
+++ b/src/eepp/ui/css/mediaquery.cpp
@@ -94,14 +94,7 @@ MediaQuery::ptr MediaQuery::parse( const std::string& str ) {
StyleSheetLength length =
StyleSheetLength::fromString( exprTokens[1] );
expr.valStr = String::toLower( exprTokens[1] );
-
- if ( length.getUnit() == StyleSheetLength::Unit::Dpcm ||
- length.getUnit() == StyleSheetLength::Unit::Dpi ) {
- expr.val = (int)( length.getValue() * 2.54 );
- } else {
- expr.val = (int)length.asPixels( 0, Sizef::Zero, dpi );
- }
-
+ expr.val = (int)length.asPixels( 0, Sizef::Zero, dpi );
expr.fval = length.getValue();
}
}
diff --git a/src/eepp/ui/css/stylesheetlength.cpp b/src/eepp/ui/css/stylesheetlength.cpp
index 7eaafccc2..76e47e948 100644
--- a/src/eepp/ui/css/stylesheetlength.cpp
+++ b/src/eepp/ui/css/stylesheetlength.cpp
@@ -30,6 +30,7 @@ enum UnitHashes : String::HashType {
Dprd = String::hash( "dprd" ),
Dpru = String::hash( "dpru" ),
Dpr = String::hash( "dpr" ),
+ Ch = String::hash( "ch" ),
};
enum PercentagePositions : String::HashType {
@@ -116,6 +117,8 @@ StyleSheetLength::Unit StyleSheetLength::unitFromString( std::string unitStr ) {
return Unit::Dpru;
case UnitHashes::Dpr:
return Unit::Dpr;
+ case UnitHashes::Ch:
+ return Unit::Ch;
}
return Unit::Dp;
}
@@ -162,6 +165,8 @@ std::string StyleSheetLength::unitToString( const StyleSheetLength::Unit& unit )
return "dpru";
case Unit::Dpr:
return "dpr";
+ case Unit::Ch:
+ return "ch";
}
return "px";
}
@@ -234,6 +239,7 @@ 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::Pt:
@@ -266,6 +272,10 @@ Float StyleSheetLength::asPixels( const Float& parentSize, const Sizef& viewSize
case Unit::Rem:
ret = globalFontSize * mValue;
break;
+ case Unit::Dpi:
+ case Unit::Dpcm:
+ ret = (int)( mValue * 2.54 );
+ break;
case Unit::Px:
default:
ret = mValue;
diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp
index 5ae111b17..c2deba159 100644
--- a/src/eepp/ui/uifiledialog.cpp
+++ b/src/eepp/ui/uifiledialog.cpp
@@ -667,8 +667,12 @@ void UIFileDialog::open() {
}
void UIFileDialog::onPressEnter( const Event* ) {
- if ( FileSystem::isDirectory( mPath->getText() ) ||
- ( FDLG_DRIVE_PATH == mPath->getText().toUtf8() && !Sys::getLogicalDrives().empty() ) ) {
+ if ( allowFolderSelect() && FileSystem::isDirectory( mPath->getText() ) ) {
+ setCurPath( mPath->getText() );
+ open();
+ } else if ( FileSystem::isDirectory( mPath->getText() ) ||
+ ( FDLG_DRIVE_PATH == mPath->getText().toUtf8() &&
+ !Sys::getLogicalDrives().empty() ) ) {
setCurPath( mPath->getText() );
} else if ( !allowFolderSelect() && FileSystem::fileExists( mPath->getText() ) ) {
String folderPath( FileSystem::fileRemoveFileName( mPath->getText() ) );
diff --git a/src/eepp/ui/uiimage.cpp b/src/eepp/ui/uiimage.cpp
index dfd57f256..1754da04c 100644
--- a/src/eepp/ui/uiimage.cpp
+++ b/src/eepp/ui/uiimage.cpp
@@ -363,12 +363,7 @@ bool UIImage::applyProperty( const StyleSheetProperty& attribute ) {
bool ownIt;
if ( uri.getScheme().empty() && !getUISceneNode()->getURI().empty() ) {
- uri = getUISceneNode()->getURI();
- std::string newPath = uri.getPath();
- if ( !path.empty() && path[0] != '/' )
- FileSystem::dirAddSlashAtEnd( newPath );
- newPath += path;
- uri.setPath( newPath );
+ uri = getUISceneNode()->solveRelativePath( uri );
path = uri.toString();
}
@@ -379,7 +374,8 @@ bool UIImage::applyProperty( const StyleSheetProperty& attribute ) {
setDrawable( createdDrawable, ownIt );
} else {
Drawable* res = NULL;
- if ( NULL != ( res = DrawableSearcher::searchByName( path ) ) )
+ if ( NULL != ( res = DrawableSearcher::searchByName(
+ path, false, getUISceneNode()->getReferer() ) ) )
setDrawable( res, res->getDrawableType() == Drawable::SPRITE );
}
break;
diff --git a/src/eepp/ui/uiscenenode.cpp b/src/eepp/ui/uiscenenode.cpp
index c3b7784ad..383a03412 100644
--- a/src/eepp/ui/uiscenenode.cpp
+++ b/src/eepp/ui/uiscenenode.cpp
@@ -1368,7 +1368,7 @@ void UISceneNode::setURI( const URI& uri ) {
mURI = uri;
}
-URI UISceneNode::getURIFromURL( const URI& url ) {
+URI UISceneNode::getURIFromURL( const URI& url ) const {
URI baseURI( url );
std::string path = baseURI.getPath();
@@ -1396,6 +1396,7 @@ URI UISceneNode::getURIFromURL( const URI& url ) {
void UISceneNode::setURIFromURL( const URI& url ) {
setURI( getURIFromURL( url ) );
+ mReferer = url;
}
void UISceneNode::openURL( URI uri ) {
diff --git a/src/eepp/ui/uiwidgetcreator.cpp b/src/eepp/ui/uiwidgetcreator.cpp
index 0999a3b32..fbf87f986 100644
--- a/src/eepp/ui/uiwidgetcreator.cpp
+++ b/src/eepp/ui/uiwidgetcreator.cpp
@@ -170,6 +170,7 @@ void UIWidgetCreator::createBaseWidgetList() {
registeredWidget["article"] = [] { return UIRichText::NewWithTag( "article" ); };
registeredWidget["footer"] = [] { return UIRichText::NewWithTag( "footer" ); };
registeredWidget["main"] = [] { return UIRichText::NewWithTag( "main" ); };
+ registeredWidget["section"] = [] { return UIRichText::NewWithTag( "section" ); };
registeredWidget["nav"] = [] { return UIRichText::NewWithTag( "nav" ); };
registeredWidget["center"] = [] { return UIRichText::NewWithTag( "center" ); };
registeredWidget["html"] = [] { return UIRichText::NewWithTag( "html" ); };
diff --git a/src/tests/unit_tests/uihtml_tests.cpp b/src/tests/unit_tests/uihtml_tests.cpp
index 8ebb3084e..2917a5eae 100644
--- a/src/tests/unit_tests/uihtml_tests.cpp
+++ b/src/tests/unit_tests/uihtml_tests.cpp
@@ -49,7 +49,7 @@ UTEST( UIHTMLTable, complexLayout ) {
32, {}, 1, false, true ),
ContextSettings( false, 0, 0, GLv_default, true, false ) );
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
-
+
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
ASSERT_TRUE( font != nullptr && font->loaded() );