Various general optimizations, inlined a bunch of functions, did a bunch of optimizations in UICodeEditor::drawMinimap, render times are about +10% faster for some common ecode escenarios.

This commit is contained in:
Martín Lucas Golini
2026-08-31 19:21:25 -03:00
parent 36200430aa
commit 6e467dbb59
18 changed files with 128 additions and 140 deletions

View File

@@ -140,7 +140,9 @@ class EE_API Font {
/** Returns the horizontal advance without requiring a renderable glyph texture. */
virtual Float getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold = false,
bool italic = false, Float outlineThickness = 0 ) const;
bool italic = false, Float outlineThickness = 0 ) const {
return getGlyph( codePoint, characterSize, bold, italic, outlineThickness ).advance;
}
/** @return The glyph drawable that represents the glyph in a texture. The glyph drawable
* allocation is managed by the font. */

View File

@@ -43,20 +43,20 @@ class EE_API GlyphDrawable : public DrawableResource {
const TexturePtr& getTexture() const;
/** @return The Texture sector that represents the GlyphDrawable */
const Rectf& getSrcRect() const;
inline const Rectf& getSrcRect() const { return mSrcRect; }
const Sizef& getDestSize() const;
inline const Sizef& getDestSize() const { return mDestSize; }
/** @return This is the same as Destination Size but with the values rounded as integers. */
Sizef getSize();
Sizef getPixelsSize();
const Float& getPixelDensity() const;
inline const Float& getPixelDensity() const { return mPixelDensity; }
void setPixelDensity( const Float& pixelDensity );
const Vector2f& getGlyphOffset() const;
inline const Vector2f& getGlyphOffset() const { return mGlyphOffset; }
void setGlyphOffset( const Vector2f& glyphOffset );
@@ -64,11 +64,11 @@ class EE_API GlyphDrawable : public DrawableResource {
void setDrawMode( const DrawMode& drawMode );
bool isItalic() const { return mIsItalic; }
inline bool isItalic() const { return mIsItalic; }
void setIsItalic( bool isItalic );
const Float& getAdvance() const;
inline const Float& getAdvance() const { return mAdvance; }
void setAdvance( Float advance );

View File

@@ -155,7 +155,7 @@ class EE_API Image {
/** @return The save type from a given extension ( example: "png" => SaveType::SAVE_TYPE_PNG )
*/
static SaveType extensionToSaveType( const std::string& Extension );
static SaveType extensionToSaveType( std::string_view extension );
/** @return Convert the number of channels to a pixel format */
static PixelFormat channelsToPixelFormat( const Uint32& channels );

View File

@@ -28,7 +28,9 @@ class EE_API LineWrap {
static std::string fromLineWrapType( LineWrapType type );
static bool isWrapChar( String::StringBaseType ch );
static inline bool isWrapChar( String::StringBaseType ch ) {
return ch == ' ' || ch == '.' || ch == '-' || ch == ',';
}
static LineWrapInfo
computeLineBreaks( const String::View& string, Font* font, Uint32 characterSize, Float maxWidth,
@@ -88,8 +90,13 @@ class EE_API LineWrap {
Uint32 fontStyle, Float outlineThickness, Uint32 tabWidth = 0.f,
Float maxWidth = 0.f, bool tabStops = false );
static Float computeOffsets( const String::View& string, const FontStyleConfig& fontStyle,
Uint32 tabWidth, Float maxWidth = 0.f, bool tabStops = false );
static inline Float computeOffsets( const String::View& string,
const FontStyleConfig& fontStyle, Uint32 tabWidth,
Float maxWidth = 0.f, bool tabStops = false ) {
return LineWrap::computeOffsets( string, fontStyle.Font, fontStyle.CharacterSize,
fontStyle.Style, fontStyle.OutlineThickness, tabWidth,
maxWidth, tabStops );
}
protected:
template <typename T>

View File

@@ -324,9 +324,9 @@ class EE_API Renderer {
void getCompressedTexImage( unsigned int target, int level, void* pixels );
const bool& quadsSupported() const;
inline bool quadsSupported() const { return mQuadsSupported; }
const int& quadVertex() const;
inline int quadVertex() const { return mQuadVertex; }
ClippingMask* getClippingMask() const;

View File

@@ -48,8 +48,18 @@ class EE_API Text {
( textDrawHints & ( TextHints::AllLatin1 | TextHints::AllAscii ) ) != 0;
}
static Float tabAdvance( Float spaceHorizontalAdvance, Uint32 tabLength,
std::optional<Float> tabOffset );
static inline Float tabAdvance( Float spaceHorizontalAdvance, Uint32 tabLength,
std::optional<Float> tabOffset ) {
Float advance = spaceHorizontalAdvance * tabLength;
if ( tabOffset ) {
Float offset = fmodf( *tabOffset, advance );
advance = advance - offset;
// If there is not enough space until the next stop, skip it
if ( advance < spaceHorizontalAdvance )
advance += spaceHorizontalAdvance * tabLength;
}
return advance;
}
static std::string styleFlagToString( const Uint32& flags );

View File

@@ -157,7 +157,7 @@ class EE_API MediaQueryList {
static MediaQueryList::ptr parse( const std::string& str );
bool isUsed() const;
inline bool isUsed() const { return mUsed; }
bool applyMediaFeatures( const MediaFeatures& features ); // returns true if the isUsed changed

View File

@@ -57,7 +57,7 @@ class EE_API StyleSheetStyle {
void setVariable( const StyleSheetVariable& variable, bool setSelectorSpecificity = true );
bool isMediaValid() const { return !mMediaQueryList || mMediaQueryList->isUsed(); }
inline bool isMediaValid() const { return !mMediaQueryList || mMediaQueryList->isUsed(); }
const MediaQueryList::ptr& getMediaQueryList() const;

View File

@@ -87,11 +87,6 @@ const FontType& Font::getType() const {
return mType;
}
Float Font::getGlyphAdvance( Uint32 codePoint, unsigned int characterSize, bool bold, bool italic,
Float outlineThickness ) const {
return getGlyph( codePoint, characterSize, bold, italic, outlineThickness ).advance;
}
const std::string& Font::getName() const {
return mFontName;
}

View File

@@ -98,14 +98,6 @@ const TexturePtr& GlyphDrawable::getTexture() const {
return mTexture;
}
const Rectf& GlyphDrawable::getSrcRect() const {
return mSrcRect;
}
const Sizef& GlyphDrawable::getDestSize() const {
return mDestSize;
}
Sizef GlyphDrawable::getSize() {
if ( mDestSize != Sizef::Zero )
return Sizef( mDestSize.getWidth() / mPixelDensity, mDestSize.getHeight() / mPixelDensity );
@@ -118,18 +110,10 @@ Sizef GlyphDrawable::getPixelsSize() {
return Sizef( mSrcRect.Right, mSrcRect.Bottom );
}
const Float& GlyphDrawable::getPixelDensity() const {
return mPixelDensity;
}
void GlyphDrawable::setPixelDensity( const Float& pixelDensity ) {
mPixelDensity = pixelDensity;
}
const Vector2f& GlyphDrawable::getGlyphOffset() const {
return mGlyphOffset;
}
void GlyphDrawable::setGlyphOffset( const Vector2f& glyphOffset ) {
mGlyphOffset = glyphOffset.roundDown();
}
@@ -146,10 +130,6 @@ void GlyphDrawable::setIsItalic( bool isItalic ) {
mIsItalic = isItalic;
}
const Float& GlyphDrawable::getAdvance() const {
return mAdvance;
}
void GlyphDrawable::setAdvance( Float advance ) {
mAdvance = advance;
}

View File

@@ -485,22 +485,23 @@ std::string Image::saveTypeToExtension( Image::SaveType Format ) {
return "";
}
Image::SaveType Image::extensionToSaveType( const std::string& Extension ) {
Image::SaveType Image::extensionToSaveType( std::string_view extension ) {
SaveType saveType = SaveType::Unknown;
if ( Extension == "tga" )
if ( String::iequals( extension, "tga" ) )
saveType = SaveType::TGA;
else if ( Extension == "bmp" )
else if ( String::iequals( extension, "bmp" ) )
saveType = SaveType::BMP;
else if ( Extension == "png" )
else if ( String::iequals( extension, "png" ) )
saveType = SaveType::PNG;
else if ( Extension == "dds" )
else if ( String::iequals( extension, "dds" ) )
saveType = SaveType::DDS;
else if ( Extension == "jpg" || Extension == "jpeg" )
else if ( String::iequals( extension, "jpg" ) || String::iequals( extension, "jpeg" ) ||
String::iequals( extension, "jfif" ) )
saveType = SaveType::JPG;
else if ( Extension == "qoi" )
else if ( String::iequals( extension, "qoi" ) )
saveType = SaveType::QOI;
else if ( Extension == "webp" )
else if ( String::iequals( extension, "webp" ) )
saveType = SaveType::WEBP;
return saveType;
@@ -654,14 +655,15 @@ Image::Format Image::getFormat( IOStream& stream ) {
bool Image::isImageExtension( const std::string& path ) {
const std::string ext( FileSystem::fileExtension( path ) );
return ( ext == "png" || ext == "tga" || ext == "bmp" || ext == "jpg" || ext == "gif" ||
ext == "jpeg" || ext == "dds" || ext == "psd" || ext == "hdr" || ext == "pic" ||
ext == "pvr" || ext == "pkm" || ext == "svg" || ext == "qoi" || ext == "webp" ||
ext == "jpe" || ext == "astc" );
ext == "jpeg" || ext == "jfif" || ext == "dds" || ext == "psd" || ext == "hdr" ||
ext == "pic" || ext == "pvr" || ext == "pkm" || ext == "svg" || ext == "qoi" ||
ext == "webp" || ext == "jpe" || ext == "astc" );
}
std::vector<std::string> Image::getImageExtensionsSupported() {
return std::vector<std::string>{ "png", "tga", "bmp", "jpg", "gif", "jpeg", "dds", "psd", "hdr",
"pic", "pvr", "pkm", "svg", "qoi", "webp", "jpe", "astc" };
return std::vector<std::string>{ "png", "tga", "bmp", "jpg", "gif", "jpeg",
"dds", "psd", "hdr", "pic", "pvr", "pkm",
"svg", "qoi", "webp", "jpe", "astc", "jfif" };
}
std::string Image::getLastFailureReason() {

View File

@@ -44,13 +44,6 @@ std::string LineWrap::fromLineWrapType( LineWrapType type ) {
}
}
Float LineWrap::computeOffsets( const String::View& string, const FontStyleConfig& fontStyle,
Uint32 tabWidth, Float maxWidth, bool tabStops ) {
return LineWrap::computeOffsets( string, fontStyle.Font, fontStyle.CharacterSize,
fontStyle.Style, fontStyle.OutlineThickness, tabWidth,
maxWidth, tabStops );
}
Float LineWrap::computeOffsets( const String::View& string, Font* font, Uint32 characterSize,
Uint32 fontStyle, Float outlineThickness, Uint32 tabWidth,
Float maxWidth, bool tabStops ) {
@@ -245,10 +238,6 @@ LineWrap::computeLineBreaksInternal( const String::View& string, Font* font, Uin
return info;
}
bool LineWrap::isWrapChar( String::StringBaseType ch ) {
return ch == ' ' || ch == '.' || ch == '-' || ch == ',';
}
LineWrapInfo LineWrap::computeLineBreaks( const String::View& string, Font* font,
Uint32 characterSize, Float maxWidth, LineWrapMode mode,
Uint32 fontStyle, Float outlineThickness,

View File

@@ -836,10 +836,6 @@ void Renderer::getColorMask( Uint8 mask[4] ) const {
std::copy( std::begin( mColorMask ), std::end( mColorMask ), mask );
}
const int& Renderer::quadVertex() const {
return mQuadVertex;
}
ClippingMask* Renderer::getClippingMask() const {
return mClippingMask;
}
@@ -1260,9 +1256,6 @@ void Renderer::genVertexArrays( int n, unsigned int* arrays ) {
#endif
}
const bool& Renderer::quadsSupported() const {
return mQuadsSupported;
}
void Renderer::waitForIdle() {
glFinish();

View File

@@ -61,18 +61,6 @@ std::string Text::fontFeaturesToString( Uint32 features ) {
return value;
}
Float Text::tabAdvance( Float hspace, Uint32 tabWidth, std::optional<Float> tabOffset ) {
Float advance = hspace * tabWidth;
if ( tabOffset ) {
Float offset = fmodf( *tabOffset, advance );
advance = advance - offset;
// If there is not enough space until the next stop, skip it
if ( advance < hspace )
advance += hspace * tabWidth;
}
return advance;
}
std::string Text::styleFlagToString( const Uint32& flags ) {
std::string str;
@@ -270,19 +258,20 @@ static inline void drawGlyph( BatchRenderer* BR, GlyphDrawable* gd, const Vector
const Color& color, bool isItalic ) {
BR->setSubpixelText( gd->getGlyphRenderMode() == GlyphRenderMode::Subpixel );
BR->quadsSetColor( color );
BR->quadsSetTexCoord( gd->getSrcRect().Left, gd->getSrcRect().Top,
gd->getSrcRect().Left + gd->getSrcRect().Right,
gd->getSrcRect().Top + gd->getSrcRect().Bottom );
const auto& srcRect = gd->getSrcRect();
const auto& offset = gd->getGlyphOffset();
const auto& destSize = gd->getDestSize();
BR->quadsSetTexCoord( srcRect.Left, srcRect.Top, srcRect.Left + srcRect.Right,
srcRect.Top + srcRect.Bottom );
if ( isItalic && !gd->isItalic() ) {
Float x = position.x + gd->getGlyphOffset().x;
Float y = position.y + gd->getGlyphOffset().y;
Float italic = 0.208f * gd->getDestSize().getWidth(); // 12 degrees
BR->batchQuadFree( x + italic, y, x, y + gd->getDestSize().getHeight(),
x + gd->getDestSize().getWidth(), y + gd->getDestSize().getHeight(),
x + gd->getDestSize().getWidth() + italic, y );
Float x = position.x + offset.x;
Float y = position.y + offset.y;
Float italic = 0.208f * destSize.getWidth(); // 12 degrees
BR->batchQuadFree( x + italic, y, x, y + destSize.getHeight(), x + destSize.getWidth(),
y + destSize.getHeight(), x + destSize.getWidth() + italic, y );
} else {
BR->batchQuad( position.x + gd->getGlyphOffset().x, position.y + gd->getGlyphOffset().y,
gd->getDestSize().getWidth(), gd->getDestSize().getHeight() );
BR->batchQuad( position.x + offset.x, position.y + offset.y, destSize.getWidth(),
destSize.getHeight() );
}
}
@@ -1074,7 +1063,7 @@ Float Text::getTextWidth( Font* font, const Uint32& fontSize, const StringType&
static_cast<FontTrueType*>( font )->isIdentifiedAsMonospace() &&
canSkipShaping( textDrawHints ) ) );
Float hspace = static_cast<Float>(
font->getGlyph( L' ', fontSize, bold, italic, outlineThickness ).advance );
font->getGlyphAdvance( L' ', fontSize, bold, italic, outlineThickness ) );
if ( isMonospace ) {
size_t len = string.length();
@@ -1139,7 +1128,7 @@ Text::findLastCharPosWithinLength( Font* font, const Uint32& fontSize, const Str
bool bold = ( style & Text::Bold ) != 0;
bool italic = ( style & Text::Italic ) != 0;
Float hspace = static_cast<Float>(
font->getGlyph( L' ', fontSize, bold, italic, outlineThickness ).advance );
font->getGlyphAdvance( L' ', fontSize, bold, italic, outlineThickness ) );
#ifdef EE_TEXT_SHAPER_ENABLED
if ( TextShaperEnabled && font->getType() == FontType::TTF &&
@@ -1212,7 +1201,7 @@ Vector2f Text::findCharacterPos( std::size_t index, Font* font, const Uint32& fo
bool bold = ( style & Text::Bold ) != 0;
bool italic = ( style & Italic ) != 0;
Float hspace = static_cast<Float>(
font->getGlyph( L' ', fontSize, bold, italic, outlineThickness ).advance );
font->getGlyphAdvance( L' ', fontSize, bold, italic, outlineThickness ) );
Float vspace = static_cast<Float>( font->getLineSpacing( fontSize ) );
// Compute the position, starting from initialOffset
@@ -1463,7 +1452,7 @@ Int32 Text::findCharacterFromPos( const Vector2i& pos, bool returnNearest, Font*
Vector2f fpos( adjX, adjY );
Float hspace = static_cast<Float>(
font->getGlyph( L' ', fontSize, bold, italic, outlineThickness ).advance );
font->getGlyphAdvance( L' ', fontSize, bold, italic, outlineThickness ) );
#ifdef EE_TEXT_SHAPER_ENABLED
if ( TextShaperEnabled && font->getType() == FontType::TTF &&

View File

@@ -448,8 +448,4 @@ MediaQueryList::MediaQueryList() {
mUsed = false;
}
bool MediaQueryList::isUsed() const {
return mUsed;
}
}}} // namespace EE::UI::CSS

View File

@@ -5206,6 +5206,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
Float lineY = rect.Top;
const auto* batchSyntaxType = &SYNTAX_NORMAL;
auto colorSyntaxType = *batchSyntaxType;
Color color = mColorScheme.getSyntaxStyle( *batchSyntaxType ).color;
color.a *= 0.5f;
Float batchWidth = 0;
@@ -5213,22 +5214,24 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
Float minimapCutoffX = rect.Left + rect.getWidth();
Float widthScale = charSpacing / getGlyphWidth();
Int64 maxVisibleColumn = eeceil( rect.getWidth() / charSpacing );
auto flushBatch = [this, &color, &batchSyntaxType, &batchStart, &batchWidth, &lineY, &BR,
&charHeight]( const SyntaxStyleType& type ) {
Color oldColor = color;
color = mColorScheme.getSyntaxStyle( *batchSyntaxType ).color;
if ( color != Color::Transparent ) {
color.a *= 0.5f;
} else {
color = oldColor;
auto flushBatch = [&]() {
if ( colorSyntaxType != *batchSyntaxType ) {
Color newColor = mColorScheme.getSyntaxStyle( *batchSyntaxType ).color;
if ( newColor != Color::Transparent ) {
newColor.a *= 0.5f;
color = newColor;
}
colorSyntaxType = *batchSyntaxType;
}
if ( batchWidth > 0 ) {
BR->quadsSetColor( color.blendAlpha( mAlpha ) );
BR->batchQuad( { { batchStart, lineY }, { batchWidth, charHeight } } );
}
if ( batchWidth <= 0 )
return;
BR->quadsSetColor( color.blendAlpha( mAlpha ) );
BR->batchQuad( { { batchStart, lineY }, { batchWidth, charHeight } } );
batchSyntaxType = &type;
batchStart += batchWidth;
batchWidth = 0;
};
@@ -5397,7 +5400,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
continue;
if ( *batchSyntaxType != token.type ) {
flushBatch( *batchSyntaxType );
flushBatch();
batchSyntaxType = &token.type;
}
@@ -5412,10 +5415,17 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
for ( auto i = pos; i < maxPos; i++ ) {
String::StringBaseType ch = text[i];
if ( ch == ' ' || ch == '\n' ) {
flushBatch( token.type );
flushBatch();
batchSyntaxType = &token.type;
batchStart += charSpacing;
while ( i + 1 < maxPos &&
( text[i + 1] == ' ' || text[i + 1] == '\n' ) ) {
++i;
batchStart += charSpacing;
}
} else if ( ch == '\t' ) {
flushBatch( token.type );
flushBatch();
batchSyntaxType = &token.type;
batchStart += charSpacing * mMinimapConfig.tabWidth;
} else {
batchWidth += charSpacing;
@@ -5429,7 +5439,8 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
if ( pos == nextLineCol ) {
if ( curVisualIndex >= minimapStartLine ) {
flushBatch( token.type );
flushBatch();
batchSyntaxType = &token.type;
lineY += lineSpacing;
}
@@ -5460,7 +5471,7 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
Int64 tokenPos = 0;
for ( const auto& token : tokens ) {
if ( *batchSyntaxType != token.type ) {
flushBatch( *batchSyntaxType );
flushBatch();
batchSyntaxType = &token.type;
}
@@ -5469,26 +5480,40 @@ void UICodeEditor::drawMinimap( const Vector2f& start, const DocumentLineRange&,
while ( pos < end ) {
String::StringBaseType ch = text[pos];
if ( ch == ' ' || ch == '\n' ) {
flushBatch( token.type );
batchStart += charSpacing;
} else if ( ch == '\t' ) {
flushBatch( token.type );
batchStart += charSpacing * mMinimapConfig.tabWidth;
} else if ( batchStart + batchWidth > minimapCutoffX ) {
flushBatch( token.type );
break;
} else {
batchWidth += charSpacing;
flushBatch();
do {
batchStart += charSpacing;
++pos;
} while ( pos < end && ( text[pos] == ' ' || text[pos] == '\n' ) );
continue;
}
pos++;
};
if ( ch == '\t' ) {
flushBatch();
batchStart += charSpacing * mMinimapConfig.tabWidth;
++pos;
continue;
}
if ( batchStart + batchWidth > minimapCutoffX ) {
flushBatch();
break;
}
batchWidth += charSpacing;
++pos;
}
tokenPos += token.len;
}
}
flushBatch( SYNTAX_NORMAL );
flushBatch();
batchSyntaxType = &SYNTAX_NORMAL;
if ( !wrappedLine )
lineY += lineSpacing;

View File

@@ -68,7 +68,7 @@ static constexpr const char* GIT_STASH_TOOLTIP_CLASS = "git-stash-tooltip";
class GitPlugin : public PluginBase {
public:
static PluginDefinition Definition() {
return { "git", "Git", "Git integration", GitPlugin::New, { 0, 1, 5 }, GitPlugin::NewSync };
return { "git", "Git", "Git integration", GitPlugin::New, { 0, 2, 0 }, GitPlugin::NewSync };
}
static Plugin* New( PluginManager* pluginManager );

View File

@@ -235,7 +235,7 @@ void ConsoleCommands::cmdImgResize( const std::vector<String>& params ) {
myPath = params[3].toUtf8();
if ( params.size() > 4 ) {
saveType = Image::extensionToSaveType( params[4] );
saveType = Image::extensionToSaveType( params[4].toUtf8() );
}
if ( params.size() > 5 ) {
@@ -274,7 +274,7 @@ void ConsoleCommands::cmdImgThumbnail( const std::vector<String>& params ) {
myPath = params[3].toUtf8();
if ( params.size() > 4 ) {
saveType = Image::extensionToSaveType( params[4] );
saveType = Image::extensionToSaveType( params[4].toUtf8() );
}
} else {
myPath = mApp->getFilePath();
@@ -306,7 +306,7 @@ void ConsoleCommands::cmdImgCenterCrop( const std::vector<String>& params ) {
myPath = params[3].toUtf8();
if ( params.size() > 4 ) {
saveType = Image::extensionToSaveType( params[4] );
saveType = Image::extensionToSaveType( params[4].toUtf8() );
}
} else {
myPath = mApp->getFilePath();
@@ -336,7 +336,7 @@ void ConsoleCommands::cmdImgScale( const std::vector<String>& params ) {
myPath = params[2].toUtf8();
if ( params.size() > 3 ) {
saveType = Image::extensionToSaveType( params[3] );
saveType = Image::extensionToSaveType( params[3].toUtf8() );
}
if ( params.size() > 4 ) {