Added support for data:image URIs.

StyleSheetPropertiesParser: fix quoted text reading.
ecode: ProjectDirectoryTree fix recursive directories scan.
This commit is contained in:
Martín Lucas Golini
2022-08-06 03:06:16 -03:00
parent b11b436903
commit 46dad2ac63
6 changed files with 134 additions and 32 deletions

View File

@@ -502,6 +502,13 @@ TabWidget {
margin-right: 8dp;
}
#tm {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAA/UlEQVR42u3ZsQkAMAhFwW/I/iubIQIp4l1vIw8srE46jLWsQAAIAAEgAASAABAAAkAACAABIAAEwKf21bRH8vAAkqRU4AQgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAKwAgEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAAIAAEgAASAABAAAkAACAABIAAEgAAQAAJAAAgAASAABIAAEAACQAA8dwB+IAUBZkHfLAAAAABJRU5ErkJggg=="),
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='45'%3E%3Cpath d='M10 10h60' stroke='%2300F' stroke-width='5'/%3E%3Cpath d='M10 20h60' stroke='%230F0' stroke-width='5'/%3E%3Cpath d='M10 30h60' stroke='red' stroke-width='5'/%3E%3C/svg%3E");
background-repeat: none;
background-position: 0 0, 64dp 0dp;
}
@media screen and (max-width: 1024px) {
#lvbox {

View File

@@ -280,6 +280,10 @@ Sets if the element skin background should be expanded to the element dimensions
Read [background-image](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image) documentation.
* Applicable to: Any element
* Data Type: [resource-path](#resource-path-data-type)
* Default value: `none`
---
### background-position-x
@@ -601,6 +605,10 @@ Same as [background-color](#background-color) but for the foreground.
Same as [background-image](#background-image) but for the foreground.
* Applicable to: Any element
* Data Type: [resource-path](#resource-path-data-type)
* Default value: `none`
---
### foreground-position-x
@@ -776,7 +784,7 @@ The mode defines the visibility of the horizontal scroll.
Sets an icon to an element that support icons.
* Applicable to: EE::UI::UIImage (Image), EE::UI::UIPushButton (PushButton), EE::UI::UITab (Tab)
* Data Type: resource-path (`url()`)
* Data Type: [resource-path](#resource-path-data-type)
* Default value: _No value_
---
@@ -1550,35 +1558,9 @@ Sets the space ocuppied by the first view contained by the splitter.
Sets the source of a resource in an element that supports source.
* Applicable to: EE::UI::UIImage (Image), EE::UI::UISprite (Sprite), EE::UI::UITextureRegion (TextureRegion)
* Data Type: [string](#string-data-type)
* Data Type: [resource-path](#resource-path-data-type)
* Default value: _No value_
Syntax:
For Image (all the examples are valid).
For a TextureRegion only the examples with: @textureregion, @drawable, drawable_resource_name
from a texture region resource are valid.
For a Sprite only the examples with: all the examples are valid except for @9p and http/s resources.
```CSS
src: file://assets/icon/ee.png; /** relative path to the current working diretory */
src: "file://assets/icon/ee.png";
src: https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png;
src: "https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png";
src: url(file://assets/icon/ee.png);
src: url(https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png);
src: url("file://assets/icon/ee.png");
src: @image/image_name_already_in_texture_factory;
src: @texture/image_name_already_in_texture_factory;
src: @textureregion/region_name_already_in_any_texture_atlas;
src: @sprite/sprite_name_already_in_any_texture_atlas; /* sprite pattern name **/
src: @drawable/drawable_name_already_in_any_drawable_manager; /* drawable managers are any holder of image resources. This includes: texture atlases, textures, nine patchs. */
src: @9p/nine_patch_resource_name_already_in_the_nine_path_manager;
src: drawable_resource_name; /** same as doing: @drawable/drawable_resource_name */
```
---
### tabbar-hide-on-single-tab
@@ -2314,6 +2296,45 @@ Read [number](https://developer.mozilla.org/en-US/docs/Web/CSS/number) documenta
Read [position](https://developer.mozilla.org/en-US/docs/Web/CSS/position_value) documentation.
---
### resource-path (data-type)
For EE::UI::UIImage (Image), background-image, foreground-image (all the examples are valid).
For a EE::UI::UITextureRegion (TextureRegion) only the examples with: @textureregion, @drawable,
drawable_resource_name from a texture region resource are valid.
For a EE::UI::UISprite (Sprite) only the examples with: all the examples are valid except for @9p
and http/s resources.
Valid resources path:
```CSS
file://assets/icon/ee.png; /** relative path to the current working diretory */
"file://assets/icon/ee.png";
https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png;
"https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png";
url(file://assets/icon/ee.png);
url(https://raw.githubusercontent.com/SpartanJ/eepp/develop/bin/assets/icon/ee.png);
url("file://assets/icon/ee.png");
url(data:image/format;base64,data);
url(data:image/format,url-encoded-data);
@image/image_name_already_in_texture_factory;
@texture/image_name_already_in_texture_factory;
@textureregion/region_name_already_in_any_texture_atlas;
@sprite/sprite_name_already_in_any_texture_atlas; /* sprite pattern name **/
@drawable/drawable_name_already_in_any_drawable_manager; /* drawable managers are any holder of image resources. This includes: texture atlases, textures, nine patchs. */
@9p/nine_patch_resource_name_already_in_the_nine_path_manager;
drawable_resource_name; /** same as doing: @drawable/drawable_resource_name */
linear-gradient(from_color, to_color);
linear-gradient(direction, from_color, to_color); /** valid directions are (without quotes): "to bottom", "to left", "to right", "to top". */
circle(type, color); /** type (optional) can be (without quotes): "fill" or "solid" (filled), or "line" (lined). */
rectangle(type, color, rotation, radius); /** type (optional) can be (without quotes): "fill" or "solid" (filled), or "line" (lined). rotation (optional) is a number in degress: "0º" (without quotes). radius (optional), must be the last parameter. */
triangle(type, color, "point_1.x point1.y, point_2.x point2.y, point_3.x point3.y") /** type can be (without quotes): "fill" or "solid" (filled), or "line" (lined). */
poly(type, color, "point_1.x point1.y, point_2.x point2.y, ...") /** polygon. type (optional) can be (without quotes): "fill" or "solid" (filled), or "line" (lined). */
```
---
### string (data-type)

View File

@@ -4,6 +4,8 @@
#include <eepp/graphics/sprite.hpp>
#include <eepp/graphics/textureatlasmanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/base64.hpp>
#include <eepp/system/md5.hpp>
#include <eepp/network/http.hpp>
#include <eepp/network/uri.hpp>
@@ -45,6 +47,61 @@ static Drawable* searchByNameInternal( const std::string& name ) {
return drawable;
}
static Drawable* parseDataURI( const std::string& name ) {
auto hash = MD5::fromString( name ).toHexString();
Drawable* drawable = TextureFactory::instance()->getByName( hash );
std::string::size_type formatAndEncSep;
if ( nullptr == drawable &&
( formatAndEncSep = name.find_first_of( ',' ) ) != std::string::npos ) {
std::string decodingType = "urldecode";
std::string mediaType = name.substr( 0, formatAndEncSep );
std::string format;
auto parts = String::split( mediaType, ';' );
if ( parts.empty() )
return nullptr;
auto formatNamePos = parts[0].find_first_of( '/' );
if ( formatNamePos + 1 < mediaType.size() )
format = parts[0].substr( formatNamePos + 1 );
if ( parts.size() > 1 ) {
for ( size_t i = 1; i < parts.size(); ++i ) {
if ( "base64" == parts[i] ) {
decodingType = parts[i];
break;
}
}
}
Uint32 texId = 0;
if ( !format.empty() &&
( Image::isImageExtension( "." + format ) || format == "svg+xml" ) ) {
if ( decodingType == "base64" ) {
int fileStart = formatAndEncSep + 1;
int base64Size = name.size() - fileStart;
int bufSize = Base64::decodeSafeOutLen( base64Size );
if ( bufSize <= 0 )
return nullptr;
ScopedBuffer buffer( bufSize );
int len = Base64::decode( base64Size, &name[fileStart], bufSize, buffer.get() );
if ( len > 0 )
texId = TextureFactory::instance()->loadFromMemory( buffer.get(), len );
} else if ( decodingType == "urldecode" ) {
int fileStart = formatAndEncSep + 1;
std::string decoded( URI::decode( name.substr( fileStart ) ) );
if ( !decoded.empty() )
texId = TextureFactory::instance()->loadFromMemory(
(const unsigned char*)decoded.c_str(), decoded.size() );
}
}
if ( texId > 0 ) {
Texture* tex = TextureFactory::instance()->getTexture( texId );
tex->setName( hash );
drawable = tex;
}
}
return drawable;
}
Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSearchSprite ) {
Drawable* drawable = NULL;
@@ -118,6 +175,8 @@ Drawable* DrawableSearcher::searchByName( const std::string& name, bool firstSea
}
drawable = texture;
} else if ( String::startsWith( name, "data:image/" ) ) {
drawable = parseDataURI( name );
} else {
drawable = searchByNameInternal( name );
}

View File

@@ -203,14 +203,18 @@ void DrawableImageParser::registerBaseParsers() {
for ( size_t i = 0; i < params.size(); i++ ) {
std::string param( String::toLower( params[i] ) );
if ( Color::isColorString( param ) ) {
if ( param == "solid" || param == "fill" ) {
drawable->setFillMode( DRAW_FILL );
} else if ( String::startsWith( param, "line" ) ) {
drawable->setFillMode( DRAW_LINE );
} else if ( Color::isColorString( param ) ) {
colors.push_back( Color::fromString( param ) );
} else {
std::vector<std::string> vertex( String::split( param, ',' ) );
if ( vertex.size() == 3 ) {
for ( size_t v = 0; v < vertex.size(); v++ ) {
vertex[v] = String::trim( vertex[v] );
String::trimInPlace( vertex[v] );
std::vector<std::string> coords( String::split( vertex[v], ' ' ) );
if ( coords.size() == 2 ) {
@@ -302,7 +306,7 @@ void DrawableImageParser::registerBaseParsers() {
};
mFuncs["url"] = []( const FunctionString& functionType, const Sizef& /*size*/, bool& /*ownIt*/,
UINode *
UINode*
/*node*/ ) -> Drawable* {
if ( functionType.getParameters().size() < 1 ) {
return NULL;

View File

@@ -87,13 +87,16 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R
mPrevRs = rs;
bool inString = false;
int prevChar = -1;
while ( pos < str.size() ) {
if ( str[pos] == '/' && str.size() > pos + 1 && str[pos + 1] == '*' ) {
rs = ReadingComment;
return pos;
}
if ( str[pos] == ';' ) {
if ( str[pos] == ';' && !inString ) {
rs = ReadingPropertyName;
addProperty( propName, buffer );
@@ -101,6 +104,9 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R
return pos + 1;
}
if ( str[pos] == '"' && prevChar != '\\' )
inString = !inString;
if ( str[pos] != '\n' && str[pos] != '\r' && str[pos] != '\t' )
buffer += str[pos];
@@ -113,6 +119,8 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R
return pos + 1;
}
prevChar = str[pos - 1];
}
return pos;

View File

@@ -167,6 +167,9 @@ void ProjectDirectoryTree::getDirectoryFiles( std::vector<std::string>& files,
FileSystem::dirAddSlashAtEnd( fullpath );
if ( currentDirs.find( fullpath ) == currentDirs.end() )
continue;
if ( std::find( mDirectories.begin(), mDirectories.end(), fullpath ) !=
mDirectories.end() )
continue;
mDirectories.push_back( fullpath );
} else {
mDirectories.push_back( fullpath );