diff --git a/bin/emscripten-fs.html b/bin/emscripten-fs.html
index a10d264a6..41565b144 100644
--- a/bin/emscripten-fs.html
+++ b/bin/emscripten-fs.html
@@ -1,4 +1,5 @@
+
@@ -63,7 +64,7 @@
function getDemoScript(name) {
if (name)
return name;
- return "eepp-test-debug.js";
+ return "ecode.js";
}
function getParameter(name) {
@@ -108,8 +109,9 @@
monitorRunDependencies: function(left) {
// no run dependencies to log
},
- };
- window.onerror = function() {
+ arguments: window.location.search.substr(1).split('&')
+ };
+ window.onerror = function() {
console.log("onerror: " + event);
};
diff --git a/include/eepp/graphics/fonttruetype.hpp b/include/eepp/graphics/fonttruetype.hpp
index 2cf2b443b..928400e09 100644
--- a/include/eepp/graphics/fonttruetype.hpp
+++ b/include/eepp/graphics/fonttruetype.hpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
namespace EE { namespace System {
class Pack;
@@ -65,10 +66,14 @@ class EE_API FontTrueType : public Font {
bool isMonospace() const;
- bool isEmojiFont() const { return mIsEmojiFont; }
+ bool isEmojiFont() const;
bool hasGlyph( Uint32 codePoint ) const;
+ void setIsColorEmojiFont( bool isColorEmojiFont );
+
+ void setIsEmojiFont( bool isEmojiFont );
+
protected:
explicit FontTrueType( const std::string& FontName );
@@ -85,7 +90,7 @@ class EE_API FontTrueType : public Font {
typedef std::map GlyphDrawableTable;
struct Page {
- Page();
+ Page( const Uint32 fontInternalId );
~Page();
@@ -95,6 +100,7 @@ class EE_API FontTrueType : public Font {
Texture* texture; ///< Texture containing the pixels of the glyphs
unsigned int nextRow; ///< Y position of the next new row in the texture
std::vector rows; ///< List containing the position of all the existing rows
+ Uint32 fontInternalId{ 0 };
};
void cleanup();
@@ -106,6 +112,8 @@ class EE_API FontTrueType : public Font {
const Glyph& getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
Float outlineThickness, Page& page, const Float& forzeSize ) const;
+ Uint32 getGlyphIndex( const Uint32& codePoint ) const;
+
Glyph loadGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
Float outlineThickness, Page& page, const Float& forceSize = 0.f ) const;
@@ -113,7 +121,9 @@ class EE_API FontTrueType : public Font {
bool setCurrentSize( unsigned int characterSize ) const;
- typedef std::map
+ Page& getPage( unsigned int characterSize ) const;
+
+ typedef std::map>
PageTable; ///< Table mapping a character size to its page (texture)
void* mLibrary; ///< Pointer to the internal library interface (it is typeless to avoid exposing
@@ -134,8 +144,10 @@ class EE_API FontTrueType : public Font {
bool mIsColorEmojiFont{ false };
bool mIsEmojiFont{ false };
mutable std::map mClosestCharacterSize;
+ mutable std::map mCodePointIndexCache;
- Uint64 getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const;
+ Uint64 getIndexKey( Uint32 fontInternalId, Uint32 index, bool bold,
+ Float outlineThickness ) const;
};
}} // namespace EE::Graphics
diff --git a/src/eepp/graphics/font.cpp b/src/eepp/graphics/font.cpp
index 344f8e82c..97d6d5b68 100644
--- a/src/eepp/graphics/font.cpp
+++ b/src/eepp/graphics/font.cpp
@@ -12,9 +12,9 @@ bool Font::isEmojiCodePoint( const Uint32& codePoint ) {
const Uint32 rangeMax2 = 127569;
const Uint32 rangeMin3 = 8987;
const Uint32 rangeMax3 = 12953;
- return ( ( rangeMin <= codePoint && codePoint <= rangeMax ) ||
- ( rangeMin2 <= codePoint && codePoint <= rangeMax2 ) ||
- ( rangeMin3 <= codePoint && codePoint <= rangeMax3 ) );
+ return codePoint > 8987 && ( ( rangeMin <= codePoint && codePoint <= rangeMax ) ||
+ ( rangeMin2 <= codePoint && codePoint <= rangeMax2 ) ||
+ ( rangeMin3 <= codePoint && codePoint <= rangeMax3 ) );
}
bool Font::containsEmojiCodePoint( const String& string ) {
diff --git a/src/eepp/graphics/fonttruetype.cpp b/src/eepp/graphics/fonttruetype.cpp
index 3112dd5a3..6e52cca59 100644
--- a/src/eepp/graphics/fonttruetype.cpp
+++ b/src/eepp/graphics/fonttruetype.cpp
@@ -14,6 +14,7 @@
#include FT_BITMAP_H
#include FT_STROKER_H
#include FT_TRUETYPE_TABLES_H
+#include
#include
#include
@@ -43,8 +44,10 @@ template inline T reinterpret( const U& input ) {
}
// Combine outline thickness, boldness and font glyph index into a single 64-bit key
-EE::Uint64 combine( float outlineThickness, bool bold, EE::Uint32 index ) {
- return ( static_cast( reinterpret( outlineThickness * 100 ) ) << 33 ) |
+EE::Uint64 combine( float outlineThickness, bool bold, EE::Uint32 index,
+ EE::Uint32 fontInternalId ) {
+ return ( static_cast( reinterpret( fontInternalId ) ) << 48 ) |
+ ( static_cast( reinterpret( outlineThickness * 100 ) ) << 33 ) |
( static_cast( bold ) << 32 ) | index;
}
@@ -52,6 +55,9 @@ EE::Uint64 combine( float outlineThickness, bool bold, EE::Uint32 index ) {
namespace EE { namespace Graphics {
+static std::map fontsInternalIds;
+static std::atomic fontInternalIdCounter{ 0 };
+
FontTrueType* FontTrueType::New( const std::string& FontName ) {
return eeNew( FontTrueType, ( FontName ) );
}
@@ -156,6 +162,10 @@ bool FontTrueType::loadFromFile( const std::string& filename ) {
// Store the font information
mInfo.family = face->family_name ? face->family_name : std::string();
+ auto fontInternalId = fontsInternalIds.find( mInfo.family );
+ if ( fontsInternalIds.end() == fontInternalId )
+ fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
+
sendEvent( Event::Load );
return true;
@@ -226,6 +236,10 @@ bool FontTrueType::loadFromMemory( const void* data, std::size_t sizeInBytes, bo
// Store the font information
mInfo.family = face->family_name ? face->family_name : std::string();
+ auto fontInternalId = fontsInternalIds.find( mInfo.family );
+ if ( fontsInternalIds.end() == fontInternalId )
+ fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
+
sendEvent( Event::Load );
return true;
@@ -309,6 +323,10 @@ bool FontTrueType::loadFromStream( IOStream& stream ) {
// Store the font information
mInfo.family = face->family_name ? face->family_name : std::string();
+ auto fontInternalId = fontsInternalIds.find( mInfo.family );
+ if ( fontsInternalIds.end() == fontInternalId )
+ fontsInternalIds[mInfo.family] = ++fontInternalIdCounter;
+
sendEvent( Event::Load );
return true;
@@ -333,18 +351,30 @@ const FontTrueType::Info& FontTrueType::getInfo() const {
return mInfo;
}
-Uint64 FontTrueType::getIndexKey( Uint32 index, bool bold, Float outlineThickness ) const {
- return combine( outlineThickness, bold, index );
+Uint64 FontTrueType::getIndexKey( Uint32 fontInternalId, Uint32 index, bool bold,
+ Float outlineThickness ) const {
+ return combine( outlineThickness, bold, index, fontInternalId );
}
bool FontTrueType::hasGlyph( Uint32 codePoint ) const {
- return FT_Get_Char_Index( static_cast( mFace ), codePoint ) != 0;
+ return getGlyphIndex( codePoint ) != 0;
+}
+
+Uint32 FontTrueType::getGlyphIndex( const Uint32& codePoint ) const {
+ Uint32 index;
+ auto indexIter = mCodePointIndexCache.find( codePoint );
+ if ( mCodePointIndexCache.end() != indexIter ) {
+ index = indexIter->second;
+ } else {
+ index = FT_Get_Char_Index( static_cast( mFace ), codePoint );
+ mCodePointIndexCache[codePoint] = index;
+ }
+ return index;
}
const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
Float outlineThickness ) const {
- FT_Face face = static_cast( mFace );
- Uint32 index = FT_Get_Char_Index( face, codePoint );
+ Uint32 index = getGlyphIndex( codePoint );
if ( Font::isEmojiCodePoint( codePoint ) && !mIsColorEmojiFont && !mIsEmojiFont ) {
if ( !mIsColorEmojiFont && FontManager::instance()->getColorEmojiFont() != nullptr &&
@@ -360,7 +390,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
FontTrueType* fontEmoji =
static_cast( FontManager::instance()->getColorEmojiFont() );
return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness,
- mPages[characterSize], maxWidth );
+ getPage( characterSize ), maxWidth );
} else if ( !mIsEmojiFont && FontManager::instance()->getEmojiFont() != nullptr &&
FontManager::instance()->getEmojiFont()->getType() == FontType::TTF ) {
@@ -370,11 +400,10 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
Glyph monospaceGlyph = getGlyph( ' ', characterSize, bold, outlineThickness );
maxWidth = monospaceGlyph.advance;
}
-
FontTrueType* fontEmoji =
static_cast( FontManager::instance()->getEmojiFont() );
return fontEmoji->getGlyph( codePoint, characterSize, bold, outlineThickness,
- mPages[characterSize], maxWidth );
+ getPage( characterSize ), maxWidth );
}
}
@@ -384,8 +413,7 @@ const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSiz
const Glyph& FontTrueType::getGlyph( Uint32 codePoint, unsigned int characterSize, bool bold,
Float outlineThickness, Page& page,
const Float& forzeSize ) const {
- FT_Face face = static_cast( mFace );
- Uint32 index = FT_Get_Char_Index( face, codePoint );
+ Uint32 index = getGlyphIndex( codePoint );
return getGlyphByIndex( index, characterSize, bold, outlineThickness, page, forzeSize );
}
@@ -396,7 +424,7 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
GlyphTable& glyphs = page.glyphs;
// Build the key by combining the code point, bold flag, and outline thickness
- Uint64 key = getIndexKey( index, bold, outlineThickness );
+ Uint64 key = getIndexKey( fontsInternalIds[mInfo.family], index, bold, outlineThickness );
// Search the glyph into the cache
GlyphTable::const_iterator it = glyphs.find( key );
@@ -413,22 +441,23 @@ const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int character
const Glyph& FontTrueType::getGlyphByIndex( Uint32 index, unsigned int characterSize, bool bold,
Float outlineThickness ) const {
- return getGlyphByIndex( index, characterSize, bold, outlineThickness, mPages[characterSize],
+ return getGlyphByIndex( index, characterSize, bold, outlineThickness, getPage( characterSize ),
0.f );
}
GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int characterSize,
bool bold, Float outlineThickness ) const {
- GlyphDrawableTable& drawables = mPages[characterSize].drawables;
+ GlyphDrawableTable& drawables = getPage( characterSize ).drawables;
- Uint64 key = getIndexKey( codePoint, bold, outlineThickness );
+ Uint64 key = getIndexKey( getPage( characterSize ).fontInternalId, getGlyphIndex( codePoint ),
+ bold, outlineThickness );
auto it = drawables.find( key );
if ( it != drawables.end() ) {
return it->second;
} else {
const Glyph& glyph = getGlyph( codePoint, characterSize, bold, outlineThickness );
- auto& page = mPages[characterSize];
+ auto& page = getPage( characterSize );
GlyphDrawable* region = GlyphDrawable::New(
page.texture, glyph.textureRect,
String::format( "%s_%d_%u", mFontName.c_str(), characterSize, codePoint ) );
@@ -442,15 +471,15 @@ GlyphDrawable* FontTrueType::getGlyphDrawable( Uint32 codePoint, unsigned int ch
Float FontTrueType::getKerning( Uint32 first, Uint32 second, unsigned int characterSize,
bool bold ) const {
// Special case where first or second is 0 (null character)
- if ( first == 0 || second == 0 )
+ if ( first == 0 || second == 0 || isMonospace() )
return 0.f;
FT_Face face = static_cast( mFace );
if ( face && setCurrentSize( characterSize ) ) {
// Convert the characters to indices
- FT_UInt index1 = FT_Get_Char_Index( face, first );
- FT_UInt index2 = FT_Get_Char_Index( face, second );
+ FT_UInt index1 = getGlyphIndex( first );
+ FT_UInt index2 = getGlyphIndex( second );
// Retrieve position compensation deltas generated by FT_LOAD_FORCE_AUTOHINT flag
auto firstRsbDelta = static_cast( getGlyph( first, characterSize, bold ).rsbDelta );
@@ -543,7 +572,7 @@ Float FontTrueType::getUnderlineThickness( unsigned int characterSize ) const {
}
Texture* FontTrueType::getTexture( unsigned int characterSize ) const {
- return mPages[characterSize].texture;
+ return getPage( characterSize ).texture;
}
bool FontTrueType::loaded() const {
@@ -998,6 +1027,24 @@ bool FontTrueType::setCurrentSize( unsigned int characterSize ) const {
}
}
+FontTrueType::Page& FontTrueType::getPage( unsigned int characterSize ) const {
+ auto pageIt = mPages.find( characterSize );
+ if ( pageIt == mPages.end() ) {
+ mPages.insert( std::make_pair( characterSize,
+ std::make_unique( fontsInternalIds[mInfo.family] ) ) );
+ pageIt = mPages.find( characterSize );
+ }
+ return *pageIt->second;
+}
+
+void FontTrueType::setIsEmojiFont( bool isEmojiFont ) {
+ mIsEmojiFont = isEmojiFont;
+}
+
+void FontTrueType::setIsColorEmojiFont( bool isColorEmojiFont ) {
+ mIsColorEmojiFont = isColorEmojiFont;
+}
+
bool FontTrueType::isColorEmojiFont() const {
return mIsColorEmojiFont;
}
@@ -1006,6 +1053,10 @@ bool FontTrueType::isMonospace() const {
return FT_IS_FIXED_WIDTH( static_cast( mFace ) );
}
+bool FontTrueType::isEmojiFont() const {
+ return mIsEmojiFont;
+}
+
bool FontTrueType::getBoldAdvanceSameAsRegular() const {
return mBoldAdvanceSameAsRegular;
}
@@ -1014,7 +1065,8 @@ void FontTrueType::setBoldAdvanceSameAsRegular( bool boldAdvanceSameAsRegular )
mBoldAdvanceSameAsRegular = boldAdvanceSameAsRegular;
}
-FontTrueType::Page::Page() : texture( NULL ), nextRow( 3 ) {
+FontTrueType::Page::Page( const Uint32 fontInternalId ) :
+ texture( NULL ), nextRow( 3 ), fontInternalId( fontInternalId ) {
// Make sure that the texture is initialized by default
Image image;
image.create( 128, 128, 4 );
diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp
index 5c8d6dc6f..786eb2b83 100644
--- a/src/tools/ecode/ecode.cpp
+++ b/src/tools/ecode/ecode.cpp
@@ -2060,6 +2060,10 @@ void App::initProjectTreeView( const std::string& path ) {
if ( !path.empty() ) {
if ( FileSystem::isDirectory( path ) ) {
loadFolder( path );
+ } else if ( String::startsWith( path, "https://" ) ||
+ String::startsWith( path, "http://" ) ) {
+ loadFolder( "." );
+ loadFileFromPath( path, false );
} else {
std::string rpath( FileSystem::getRealPath( path ) );
std::string folderPath( FileSystem::fileRemoveFileName( rpath ) );
@@ -2134,8 +2138,7 @@ FontTrueType* App::loadFont( const std::string& name, std::string fontPath,
return FontTrueType::New( name, fontPath );
}
-void App::init( const std::string& file, const Float& pidelDensity,
- const std::string& colorScheme ) {
+void App::init( std::string file, const Float& pidelDensity, const std::string& colorScheme ) {
DisplayManager* displayManager = Engine::instance()->getDisplayManager();
Display* currentDisplay = displayManager->getDisplayIndex( 0 );
mDisplayDPI = currentDisplay->getDPI();
@@ -2550,20 +2553,44 @@ void App::init( const std::string& file, const Float& pidelDensity,
mConsole = eeNew( Console, ( mFontMono, true, true, 1024 * 1000, 0, mWindow ) );
+#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
+ if ( file == "./this.program" )
+ file = "";
+#endif
+
initProjectTreeView( file );
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
- downloadFileWeb( "https://raw.githubusercontent.com/SpartanJ/eepp/develop/README.md" );
+ if ( file.empty() )
+ downloadFileWeb( "https://raw.githubusercontent.com/SpartanJ/eepp/develop/README.md" );
#endif
mWindow->runMainLoop( &appLoop );
}
}
+#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
+std::vector parseEmscriptenArgs( int argc, char* argv[] ) {
+ std::vector args;
+ args.emplace_back( argv[0] );
+ for ( int i = 1; i < argc; i++ ) {
+ auto split = String::split( std::string( argv[i] ), '=' );
+ if ( split.size() == 2 ) {
+ std::string arg( split[0] + "=" + URI::decode( split[1] ) );
+ args.emplace_back( !String::startsWith( arg, "--" ) ? ( std::string( "--" ) + arg )
+ : arg );
+ }
+ }
+ return args;
+}
+#endif
+
EE_MAIN_FUNC int main( int argc, char* argv[] ) {
args::ArgumentParser parser( "ecode" );
args::HelpFlag help( parser, "help", "Display this help menu", { 'h', "help" } );
- args::Positional file( parser, "file", "The file path" );
+ args::Positional file( parser, "file", "The file or folder path" );
+ args::ValueFlag filePos( parser, "file", "The file or folder path",
+ { 'f', "file", "folder" } );
args::ValueFlag pixelDenstiyConf( parser, "pixel-density",
"Set default application pixel density",
{ 'd', "pixel-density" } );
@@ -2572,7 +2599,11 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
{ 'c', "prefers-color-scheme" } );
try {
+#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
parser.ParseCLI( argc, argv );
+#else
+ parser.ParseCLI( parseEmscriptenArgs( argc, argv ) );
+#endif
} catch ( const args::Help& ) {
std::cout << parser;
return EXIT_SUCCESS;
@@ -2587,7 +2618,8 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
}
appInstance = eeNew( App, () );
- appInstance->init( file.Get(), pixelDenstiyConf ? pixelDenstiyConf.Get() : 0.f,
+ appInstance->init( filePos ? filePos.Get() : file.Get(),
+ pixelDenstiyConf ? pixelDenstiyConf.Get() : 0.f,
prefersColorScheme ? prefersColorScheme.Get() : "" );
eeSAFE_DELETE( appInstance );
diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp
index 36944576f..094cd2349 100644
--- a/src/tools/ecode/ecode.hpp
+++ b/src/tools/ecode/ecode.hpp
@@ -24,7 +24,7 @@ class App : public UICodeEditorSplitter::Client {
~App();
- void init( const std::string& file, const Float& pidelDensity, const std::string& colorScheme );
+ void init( std::string file, const Float& pidelDensity, const std::string& colorScheme );
void setAppTitle( const std::string& title );