From 62451f6fa2c7162901dbbe69295fc7ca538052d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 1 Oct 2023 02:38:46 -0300 Subject: [PATCH] More micro optimizations. --- include/eepp/graphics/fontbmfont.hpp | 4 +- include/eepp/graphics/fontsprite.hpp | 6 +- src/eepp/graphics/text.cpp | 192 ++++++++++++++++----------- src/eepp/ui/uicodeeditor.cpp | 39 +++++- 4 files changed, 153 insertions(+), 88 deletions(-) diff --git a/include/eepp/graphics/fontbmfont.hpp b/include/eepp/graphics/fontbmfont.hpp index 403fbba8d..17f21a793 100644 --- a/include/eepp/graphics/fontbmfont.hpp +++ b/include/eepp/graphics/fontbmfont.hpp @@ -63,8 +63,8 @@ class EE_API FontBMFont : public Font { protected: FontBMFont( const std::string FontName ); - typedef std::map GlyphTable; ///< Table mapping a codepoint to its glyph - typedef std::map GlyphDrawableTable; + typedef UnorderedMap GlyphTable; ///< Table mapping a codepoint to its glyph + typedef UnorderedMap GlyphDrawableTable; struct Page { ~Page(); diff --git a/include/eepp/graphics/fontsprite.hpp b/include/eepp/graphics/fontsprite.hpp index 36f138ba5..dae0968bb 100644 --- a/include/eepp/graphics/fontsprite.hpp +++ b/include/eepp/graphics/fontsprite.hpp @@ -67,8 +67,8 @@ class EE_API FontSprite : public Font { protected: FontSprite( const std::string FontName ); - typedef std::map GlyphTable; ///< Table mapping a codepoint to its glyph - typedef std::map GlyphDrawableTable; + typedef UnorderedMap GlyphTable; ///< Table mapping a codepoint to its glyph + typedef UnorderedMap GlyphDrawableTable; struct Page { ~Page(); @@ -81,7 +81,7 @@ class EE_API FontSprite : public Font { void cleanup(); - typedef std::map + typedef UnorderedMap PageTable; ///< Table mapping a character size to its page (texture) Font::Info mInfo; ///< Information about the font diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index cacb937f7..aa3baa654 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -120,6 +120,83 @@ Text* Text::New( Font* font, unsigned int characterSize ) { return eeNew( Text, ( font, characterSize ) ); } +static inline void drawGlyph( BatchRenderer* BR, GlyphDrawable* gd, const Vector2f& position, + const Color& color, bool isItalic ) { + BR->quadsSetColor( color ); + BR->quadsSetTexCoord( gd->getSrcRect().Left, gd->getSrcRect().Top, + gd->getSrcRect().Left + gd->getSrcRect().Right, + gd->getSrcRect().Top + gd->getSrcRect().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 ); + } else { + BR->batchQuad( position.x + gd->getGlyphOffset().x, position.y + gd->getGlyphOffset().y, + gd->getDestSize().getWidth(), gd->getDestSize().getHeight() ); + } +}; + +static inline void drawUnderline( Font* font, Float fontSize, const Color& fontColor, + const Vector2f& cpos, const Uint32& style, BatchRenderer* BR, + Float outlineThickness, const Vector2f& pos, Float width, + const Color& shadowColor, const Vector2f& shadowOffset, + const Color& outlineColor ) { + Float underlineOffset = font->getUnderlinePosition( fontSize ); + Float underlineThickness = font->getUnderlineThickness( fontSize ); + Float top = + cpos.y + std::floor( fontSize + underlineOffset - ( underlineThickness / 2 ) + 0.5f ); + Float bottom = top + std::floor( underlineThickness + 0.5f ); + + if ( style & Text::Shadow ) { + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( shadowColor ); + BR->batchQuad( Rectf( pos.x + shadowOffset.x, top + shadowOffset.y, + pos.x + width + shadowOffset.x, bottom + shadowOffset.y ) ); + } + + if ( outlineThickness ) { + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( outlineColor ); + BR->batchQuad( Rectf( pos.x - outlineThickness, top - outlineThickness, + pos.x + width + outlineThickness, bottom + outlineThickness ) ); + } + + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( fontColor ); + BR->batchQuad( Rectf( pos.x, top, pos.x + width, bottom ) ); +} + +static inline void drawStrikeThrough( Font* font, Float fontSize, const Color& fontColor, + const Vector2f& cpos, const Uint32& style, BatchRenderer* BR, + Float outlineThickness, const Vector2f& pos, Float width, + const Color& shadowColor, const Vector2f& shadowOffset, + const Color& outlineColor, bool isBold, bool isItalic ) { + Rectf xBounds = font->getGlyph( L'x', fontSize, isBold, isItalic ).bounds; + Float strikeThroughOffset = xBounds.Top + xBounds.Bottom * 0.5f; + Float underlineThickness = font->getUnderlineThickness( fontSize ); + Float top = + std::floor( cpos.y + fontSize + strikeThroughOffset - ( underlineThickness / 2 ) + 0.5f ); + Float bottom = top + std::floor( underlineThickness + 0.5f ); + if ( style & Text::Shadow ) { + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( shadowColor ); + BR->batchQuad( Rectf( pos.x + shadowOffset.x, top + shadowOffset.y, + pos.x + width + shadowOffset.x, bottom + +shadowOffset.y ) ); + } + if ( outlineThickness ) { + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( outlineColor ); + BR->batchQuad( Rectf( pos.x - outlineThickness, top - outlineThickness, + pos.x + width + outlineThickness, bottom + outlineThickness ) ); + } + BR->quadsSetTexCoord( 0, 0, 1, 1 ); + BR->quadsSetColor( fontColor ); + BR->batchQuad( Rectf( pos.x, top, pos.x + width, bottom ) ); +} + template Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize, const Color& fontColor, Uint32 style, Float outlineThickness, @@ -136,54 +213,10 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo Sizef size{ 0, height }; size_t ssize = string.size(); BatchRenderer* BR = GlobalBatchRenderer::instance(); + Texture* fontTexture = font->getTexture( fontSize ); BR->setBlendMode( BlendMode::Alpha() ); - - auto drawUnderline = [&]() { - Float underlineOffset = font->getUnderlinePosition( fontSize ); - Float underlineThickness = font->getUnderlineThickness( fontSize ); - Float top = - cpos.y + std::floor( fontSize + underlineOffset - ( underlineThickness / 2 ) + 0.5f ); - Float bottom = top + std::floor( underlineThickness + 0.5f ); - if ( style & Text::Shadow ) { - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( shadowColor ); - BR->batchQuad( Rectf( pos.x + shadowOffset.x, top + shadowOffset.y, - pos.x + width + shadowOffset.x, bottom + +shadowOffset.y ) ); - } - if ( outlineThickness ) { - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( outlineColor ); - BR->batchQuad( Rectf( pos.x - outlineThickness, top - outlineThickness, - pos.x + width + outlineThickness, bottom + outlineThickness ) ); - } - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( fontColor ); - BR->batchQuad( Rectf( pos.x, top, pos.x + width, bottom ) ); - }; - - auto drawStrikeThrough = [&]() { - Rectf xBounds = font->getGlyph( L'x', fontSize, isBold, isItalic ).bounds; - Float strikeThroughOffset = xBounds.Top + xBounds.Bottom * 0.5f; - Float underlineThickness = font->getUnderlineThickness( fontSize ); - Float top = std::floor( cpos.y + fontSize + strikeThroughOffset - - ( underlineThickness / 2 ) + 0.5f ); - Float bottom = top + std::floor( underlineThickness + 0.5f ); - if ( style & Text::Shadow ) { - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( shadowColor ); - BR->batchQuad( Rectf( pos.x + shadowOffset.x, top + shadowOffset.y, - pos.x + width + shadowOffset.x, bottom + +shadowOffset.y ) ); - } - if ( outlineThickness ) { - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( outlineColor ); - BR->batchQuad( Rectf( pos.x - outlineThickness, top - outlineThickness, - pos.x + width + outlineThickness, bottom + outlineThickness ) ); - } - BR->quadsSetTexCoord( 0, 0, 1, 1 ); - BR->quadsSetColor( fontColor ); - BR->batchQuad( Rectf( pos.x, top, pos.x + width, bottom ) ); - }; + BR->quadsBegin(); + BR->setTexture( fontTexture, fontTexture->getCoordinateType() ); for ( size_t i = 0; i < ssize; ++i ) { ch = string[i]; @@ -207,11 +240,15 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo continue; } case '\n': { - if ( style & Text::Underlined ) - drawUnderline(); - if ( style & Text::StrikeThrough ) - drawStrikeThrough(); - + if ( style & Text::Underlined ) { + drawUnderline( font, fontSize, fontColor, cpos, style, BR, outlineThickness, + pos, width, shadowColor, shadowOffset, outlineColor ); + } + if ( style & Text::StrikeThrough ) { + drawStrikeThrough( font, fontSize, fontColor, cpos, style, BR, outlineThickness, + pos, width, shadowColor, shadowOffset, outlineColor, isBold, + isItalic ); + } size.x = eemax( width, cpos.x ); width = 0; cpos.y += height; @@ -223,49 +260,48 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo if ( style & Text::Shadow ) { auto* gds = font->getGlyphDrawable( ch, fontSize, isBold, isItalic, outlineThickness ); - gds->setDrawMode( isItalic ? GlyphDrawable::DrawMode::TextItalic - : GlyphDrawable::DrawMode::Text ); - gds->setPosition( cpos + shadowOffset ); - gds->setColor( shadowColor ); - gds->draw(); + if ( gds ) + drawGlyph( BR, gds, cpos, shadowColor, isItalic ); } if ( outlineThickness != 0.f ) { auto* gdo = font->getGlyphDrawable( ch, fontSize, isBold, isItalic, outlineThickness ); - gdo->setDrawMode( isItalic ? GlyphDrawable::DrawMode::TextItalic - : GlyphDrawable::DrawMode::Text ); - gdo->setPosition( cpos ); - gdo->setColor( outlineColor ); - gdo->draw(); + if ( gdo ) + drawGlyph( BR, gdo, cpos, outlineColor, isItalic ); } auto* gd = font->getGlyphDrawable( ch, fontSize, isBold, isItalic ); - gd->setDrawMode( isItalic ? GlyphDrawable::DrawMode::TextItalic - : GlyphDrawable::DrawMode::Text ); - gd->setPosition( cpos ); - gd->setColor( fontColor ); - gd->draw(); + if ( gd ) { + drawGlyph( BR, gd, cpos, fontColor, isItalic ); - cpos.x += gd->getAdvance(); - width += gd->getAdvance(); + cpos.x += gd->getAdvance(); + width += gd->getAdvance(); - if ( !font->isMonospace() ) { - kerning = - font->getKerning( prevChar, ch, fontSize, isBold, isItalic, outlineThickness ); - cpos.x += kerning; - width += kerning; + if ( !font->isMonospace() ) { + kerning = + font->getKerning( prevChar, ch, fontSize, isBold, isItalic, outlineThickness ); + cpos.x += kerning; + width += kerning; + } } prevChar = ch; } - if ( ( style & Text::Underlined ) && width != 0 ) - drawUnderline(); + if ( ( style & Text::Underlined ) && width != 0 ) { + drawUnderline( font, fontSize, fontColor, cpos, style, BR, outlineThickness, pos, width, + shadowColor, shadowOffset, outlineColor ); + } - if ( ( style & Text::StrikeThrough ) && width != 0 ) - drawStrikeThrough(); + if ( ( style & Text::StrikeThrough ) && width != 0 ) { + drawStrikeThrough( font, fontSize, fontColor, cpos, style, BR, outlineThickness, pos, width, + shadowColor, shadowOffset, outlineColor, isBold, isItalic ); + } size.x = eemax( width, size.x ); + + BR->drawOpt(); + return size; } diff --git a/src/eepp/ui/uicodeeditor.cpp b/src/eepp/ui/uicodeeditor.cpp index e02ff1d75..75ab6bdc1 100644 --- a/src/eepp/ui/uicodeeditor.cpp +++ b/src/eepp/ui/uicodeeditor.cpp @@ -3462,7 +3462,8 @@ void UICodeEditor::drawMinimap( const Vector2f& start, Float batchStart = rect.Left; Float minimapCutoffX = rect.Left + rect.getWidth(); Float widthScale = charSpacing / getGlyphWidth(); - auto flushBatch = [&]( const SyntaxStyleType& type ) { + auto flushBatch = [this, &color, &batchSyntaxType, &batchStart, &batchWidth, &lineY, &BR, + &charHeight]( const SyntaxStyleType& type ) { Color oldColor = color; color = mColorScheme.getSyntaxStyle( *batchSyntaxType ).color; if ( mMinimapConfig.syntaxHighlight && color != Color::Transparent ) { @@ -3484,7 +3485,8 @@ void UICodeEditor::drawMinimap( const Vector2f& start, int endidx = minimapStartLine + maxMinmapLines; endidx = eemin( endidx, lineCount - 1 ); - auto drawWordMatch = [&]( const String& text, const Int64& ln ) { + auto drawWordMatch = [this, &lineY, &BR, &batchStart, &charHeight, &minimapCutoffX, + &widthScale]( const String& text, const Int64& ln ) { size_t pos = 0; const String& line( mDoc->line( ln ).getText() ); if ( line.size() > 300 ) @@ -3511,8 +3513,9 @@ void UICodeEditor::drawMinimap( const Vector2f& start, }; Float minimapStart = rect.Left + gutterWidth; - auto drawTextRange = [&]( const TextRange& range, const Int64& ln, - const Color& backgroundColor ) { + auto drawTextRange = [this, &lineY, &BR, &minimapStart, &charHeight, + &widthScale]( const TextRange& range, const Int64& ln, + const Color& backgroundColor ) { if ( !( ln >= range.start().line() && ln <= range.end().line() ) ) return; @@ -3547,7 +3550,9 @@ void UICodeEditor::drawMinimap( const Vector2f& start, BR->batchQuad( selRect ); }; - auto drawWordRanges = [&]( const TextRanges& ranges ) { + auto drawWordRanges = [this, &BR, &minimapStart, &charHeight, &minimapStartLine, &lineSpacing, + &rect, &minimapCutoffX, &widthScale, + &endidx]( const TextRanges& ranges ) { BR->quadsSetColor( Color( mMinimapHighlightColor ).blendAlpha( mAlpha ) ); Int64 lineSkip = -1; for ( const auto& range : ranges ) { @@ -3671,6 +3676,11 @@ void UICodeEditor::drawMinimap( const Vector2f& start, batchStart = rect.Left + gutterWidth; batchWidth = 0; + for ( auto* plugin : mPlugins ) + plugin->minimapDrawBeforeLineText( this, index, { rect.Left, lineY }, + { rect.getWidth(), charHeight }, charSpacing, + gutterWidth ); + if ( mHighlightWord.isEmpty() && !selectionString.empty() ) drawWordMatch( selectionString, index ); @@ -3691,6 +3701,25 @@ void UICodeEditor::drawMinimap( const Vector2f& start, } } flushBatch( SYNTAX_NORMAL ); + + for ( auto* plugin : mPlugins ) + plugin->minimapDrawAfterLineText( this, index, { rect.Left, lineY }, + { rect.getWidth(), charHeight }, charSpacing, + gutterWidth ); + + if ( mHighlightTextRange.isValid() && mHighlightTextRange.hasSelection() ) { + drawTextRange( mHighlightTextRange, index, + Color( mMinimapSelectionColor ).blendAlpha( mAlpha ) ); + } + + if ( mDoc->hasSelection() ) { + Color selectionColor( Color( mMinimapSelectionColor ).blendAlpha( mAlpha ) ); + auto selections = mDoc->getSelectionsSorted(); + for ( const auto& sel : selections ) { + drawTextRange( sel, index, selectionColor ); + } + } + lineY = lineY + lineSpacing; } }