Improved whitespace rendering performance on wrapped lines, now it has the same cost than non-wrapped lines.

Fixed: Debugger gutter not drawing its background.
Fixed: horizontal scrollbar sometimes being visible on wrapped documents.
Updated CSS Specification documentation.
This commit is contained in:
Martín Lucas Golini
2025-02-27 19:26:08 -03:00
parent a08148bc57
commit a91fde6dfd
6 changed files with 282 additions and 120 deletions

View File

@@ -542,6 +542,21 @@ Custom cursors not yet supported (but supported by the engine, only not implemen
---
### disable-editor-flags
Allows disabling specific behavior flags for the code editor component.
Flags set here take precedence over [enable-editor-flags](#enable-editor-flags).
Multiple flags are separated by `|`.
* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* All flags listed in [enable-editor-flags](#enable-editor-flags) can be used here to disable their respective features.
* `editorfeatures`: Macro Flag - Disables line numbers, whitespace display, folding regions, current line highlight, matching bracket highlight, selection match highlight, color picker, minimap, and find/replace. Resets line breaking and forces the editor to use the default style.
* Default value: _No value_
---
### display-percent
Enables/disables displaying the percentage of progress in the progress bar.
@@ -583,6 +598,41 @@ Sets if the element is enabled
---
### enable-editor-flags
Allows enabling specific behavior flags for the code editor component. Multiple flags can be specified, separated by `|`.
* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* `linenumber`: Displays line numbers in the gutter.
* `foldingregion`: Shows code folding regions for collapsing/expanding blocks.
* `whitespaces`: Renders whitespace characters (spaces, tabs) as visible symbols.
* `lineendings`: Displays line ending characters (e.g., CR, LF).
* `highlightcurrentline`: Highlights the background of the current line containing the cursor.
* `highlightmatchingbracket`: Highlights the bracket matching the one under the cursor.
* `highlightselectionmatch`: Highlights all occurrences of the selected text in the document.
* `colorpickeronselection`: Opens a color picker dialog when a color value is selected.
* `verticalscrollbar`: Enables the vertical scrollbar for scrolling through content.
* `horizontalscrollbar`: Enables the horizontal scrollbar for scrolling through content.
* `colorpreview`: Shows a color preview on mouse hover.
* `interactivelinks`: Enables interaction with clickable hyperlinks within the editor.
* `displayloader`: Displays a loading indicator while the document is loading.
* `defaultcontextmenu`: Provides a default context menu with standard editing options.
* `minimap`: Shows a minimap (overview) of the document on the right side.
* `autoclosexmltags`: Automatically inserts closing tags in XML/HTML documents.
* `findreplace`: Enables the find and replace functionality.
* `showindentationguides`: Displays vertical guides to indicate indentation levels.
* `linesrelativeposition`: Shows the relative position of lines (e.g., in a diff view).
* `lockedicon`: Displays a lock icon when the editor is in a locked state.
* `foldsalwaysvisible`: Keeps fold markers visible even when not hovered.
* `foldsvisible`: Makes folded code regions visible.
* `flashcursor`: Enables a flashing animation for the text cursor.
* `defaultstyle`: Applies the default styling and theme to the editor.
* Default value: _No value_
---
### font-family
Read [font-family](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family) documentation.
@@ -1052,6 +1102,33 @@ Sets a extra line spacing to the line box.
---
### line-wrap-mode
Specifies the line wrap mode of the element.
* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* `word`: Wraps against words.
* `letter`: Wraps against letters.
* `nowrap`: Does not wrap.
* Default value: `nowrap`
---
### line-wrap-type
Specifies if line must wrap against its viewport or the defined line breaking column.
* Applicable to: Any element child of a EE::UI::UICodeEditor (CodeEditor)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* `viewport`: Wrap against the element viewport.
* `line_breaking_column`: Wraps against the line breaking column.
* Default value: `viewport`
---
### locked
Enable or disable editing on code editor elements.
@@ -1462,6 +1539,22 @@ Sets the vertical separation between each element in the grid layout.
---
### row-valign
Sets the vertical alignment of the elements in a stack layout. Elements in the same row will align
based on the maximum element height in that row.
* Applicable to: EE::UI::UIStackLayout (StackLayout)
* Data Type: [string-list](#string-list-data-type)
* Value List:
* `top`: Aligns to the top of the row.
* `bottom`: Aligns to the bottom of the row.
* `center`: Aligns to the center of the row.
* Default value: `bottom`
---
### row-weight
Sets the percentage height of the child elements of a grid layout.

View File

@@ -8,6 +8,15 @@
namespace EE { namespace Graphics {
enum class CharacterAlignment : Uint32 { Left = 0, Center = 1, Right = 2 };
struct WhitespaceDisplayConfig {
String::StringBaseType spaceDisplayCharacter{ 0 };
String::StringBaseType tabDisplayCharacter{ 0 };
CharacterAlignment tabAlign{ CharacterAlignment::Center };
Color color;
};
class EE_API Text {
public:
static bool TextShaperEnabled;
@@ -48,21 +57,25 @@ class EE_API Text {
const Color& outlineColor = Color::Black,
const Color& shadowColor = Color::Black,
const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4,
Uint32 textDrawHints = 0 );
Uint32 textDrawHints = 0,
const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
static Sizef draw( const String& string, const Vector2f& pos, const FontStyleConfig& config,
const Uint32& tabWidth = 4, Uint32 textDrawHints = 0 );
const Uint32& tabWidth = 4, Uint32 textDrawHints = 0,
const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
static Sizef draw( const String::View& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f,
const Color& outlineColor = Color::Black,
const Color& shadowColor = Color::Black,
const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4,
Uint32 textDrawHints = 0 );
Uint32 textDrawHints = 0,
const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
static Sizef draw( const String::View& string, const Vector2f& pos,
const FontStyleConfig& config, const Uint32& tabWidth = 4,
Uint32 textDrawHints = 0 );
Uint32 textDrawHints = 0,
const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
static void drawUnderline( const Vector2f& pos, Float width, Font* font, Float fontSize,
const Color& fontColor, const Uint32& style, Float outlineThickness,
@@ -315,16 +328,17 @@ class EE_API Text {
const Float& outlineThickness = 0.f );
template <typename StringType>
static Sizef draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f,
const Color& outlineColor = Color::Black,
const Color& shadowColor = Color::Black,
const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4,
Uint32 textDrawHints = 0 );
static Sizef
draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style = 0, Float outlineThickness = 0.f,
const Color& outlineColor = Color::Black, const Color& shadowColor = Color::Black,
const Vector2f& shadowOffset = { 1, 1 }, const Uint32& tabWidth = 4,
Uint32 textDrawHints = 0, const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
template <typename StringType>
static Sizef draw( const StringType& string, const Vector2f& pos, const FontStyleConfig& config,
const Uint32& tabWidth = 4, Uint32 textDrawHints = 0 );
const Uint32& tabWidth = 4, Uint32 textDrawHints = 0,
const WhitespaceDisplayConfig& whitespaceDisplayConfig = {} );
template <typename StringType>
static std::size_t findLastCharPosWithinLength( Font* font, const Uint32& fontSize,

View File

@@ -33,8 +33,6 @@ class UILoader;
class UIPopUpMenu;
class UIMenuItem;
enum class CharacterAlignment : Uint32 { Left = 0, Center = 1, Right = 2 };
using DocumentLineRange = std::pair<Int64, Int64>;
using DocumentViewLineRange = std::pair<VisibleIndex, VisibleIndex>;

View File

@@ -241,27 +241,34 @@ Float Text::getTextWidth( const String::View& string, const FontStyleConfig& con
Sizef Text::draw( const String& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style, Float outlineThickness,
const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset,
const Uint32& tabWidth, Uint32 textDrawHints ) {
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
return draw<String>( string, pos, font, fontSize, fontColor, style, outlineThickness,
outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints );
outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints,
whitespaceDisplayConfig );
}
Sizef Text::draw( const String& string, const Vector2f& pos, const FontStyleConfig& config,
const Uint32& tabWidth, Uint32 textDrawHints ) {
return draw<String>( string, pos, config, tabWidth, textDrawHints );
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
return draw<String>( string, pos, config, tabWidth, textDrawHints, whitespaceDisplayConfig );
}
Sizef Text::draw( const String::View& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style, Float outlineThickness,
const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset,
const Uint32& tabWidth, Uint32 textDrawHints ) {
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
return draw<String::View>( string, pos, font, fontSize, fontColor, style, outlineThickness,
outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints );
outlineColor, shadowColor, shadowOffset, tabWidth, textDrawHints,
whitespaceDisplayConfig );
}
Sizef Text::draw( const String::View& string, const Vector2f& pos, const FontStyleConfig& config,
const Uint32& tabWidth, Uint32 textDrawHints ) {
return draw<String::View>( string, pos, config, tabWidth, textDrawHints );
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
return draw<String::View>( string, pos, config, tabWidth, textDrawHints,
whitespaceDisplayConfig );
}
Text* Text::New() {
@@ -376,7 +383,8 @@ template <typename StringType>
Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Float fontSize,
const Color& fontColor, Uint32 style, Float outlineThickness,
const Color& outlineColor, const Color& shadowColor, const Vector2f& shadowOffset,
const Uint32& tabWidth, Uint32 textDrawHints ) {
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
Vector2f cpos{ pos };
String::StringBaseType ch;
String::StringBaseType prevChar = 0;
@@ -398,94 +406,124 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
size_t ssize = string.size();
BatchRenderer* BR = GlobalBatchRenderer::instance();
Texture* fontTexture = font->getTexture( fontSize );
Float tabAlign = 0;
GlyphDrawable* spaceGlyph = nullptr;
GlyphDrawable* tabGlyph = nullptr;
Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance;
if ( whitespaceDisplayConfig.tabDisplayCharacter ) {
tabGlyph = font->getGlyphDrawable( whitespaceDisplayConfig.tabDisplayCharacter, fontSize );
switch ( whitespaceDisplayConfig.tabAlign ) {
case CharacterAlignment::Center:
tabAlign = ( ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth() ) * 0.5f;
break;
case CharacterAlignment::Right:
tabAlign = ( tabWidth * hspace ) - tabGlyph->getPixelsSize().getWidth();
break;
case CharacterAlignment::Left:
break;
}
}
BR->setBlendMode( BlendMode::Alpha() );
BR->quadsBegin();
BR->setTexture( fontTexture, fontTexture->getCoordinateType() );
#ifdef EE_TEXT_SHAPER_ENABLED
if ( TextShaperEnabled && font->getType() == FontType::TTF ) {
Float hspace = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance;
FontTrueType* rFont = static_cast<FontTrueType*>( font );
shapeAndRun( string, rFont, fontSize, style, outlineThickness,
[&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t*, Uint32 glyphCount,
const hb_segment_properties_t&, TextShapeRun& run ) {
FontTrueType* font = run.font();
Uint32 prevGlyphIndex = 0;
Uint32 cluster = 0;
for ( std::size_t i = 0; i < glyphCount; ++i ) {
hb_glyph_info_t curGlyph = glyphInfo[i];
cluster = curGlyph.cluster;
ch = string[cluster];
if ( ch == '\t' ) {
width += hspace * tabWidth;
cpos.x += hspace * tabWidth;
} else {
if ( style & Text::Shadow ) {
auto* gds = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic,
outlineThickness, rFont->getPage( fontSize ) );
if ( gds )
drawGlyph( BR, gds, cpos, shadowColor, isItalic );
}
shapeAndRun(
string, rFont, fontSize, style, outlineThickness,
[&]( hb_glyph_info_t* glyphInfo, hb_glyph_position_t*, Uint32 glyphCount,
const hb_segment_properties_t&, TextShapeRun& run ) {
FontTrueType* font = run.font();
Uint32 prevGlyphIndex = 0;
Uint32 cluster = 0;
for ( std::size_t i = 0; i < glyphCount; ++i ) {
hb_glyph_info_t curGlyph = glyphInfo[i];
cluster = curGlyph.cluster;
ch = string[cluster];
if ( ch == '\t' ) {
if ( tabGlyph ) {
drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y },
whitespaceDisplayConfig.color, isItalic );
}
width += hspace * tabWidth;
cpos.x += hspace * tabWidth;
} else {
if ( style & Text::Shadow ) {
auto* gds = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic, outlineThickness,
rFont->getPage( fontSize ) );
if ( gds )
drawGlyph( BR, gds, cpos, shadowColor, isItalic );
}
if ( outlineThickness != 0.f ) {
auto* gdo = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic,
outlineThickness, rFont->getPage( fontSize ) );
if ( gdo )
drawGlyph( BR, gdo, cpos, outlineColor, isItalic );
}
if ( outlineThickness != 0.f ) {
auto* gdo = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic, outlineThickness,
rFont->getPage( fontSize ) );
if ( gdo )
drawGlyph( BR, gdo, cpos, outlineColor, isItalic );
}
auto* gd = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic, 0,
rFont->getPage( fontSize ) );
if ( gd ) {
if ( !isMonospace ) {
kerning = font->getKerningFromGlyphIndex(
prevGlyphIndex, curGlyph.codepoint, fontSize, isBold,
isItalic, outlineThickness );
cpos.x += kerning;
width += kerning;
}
auto* gd = font->getGlyphDrawableFromGlyphIndex(
curGlyph.codepoint, fontSize, isBold, isItalic, 0,
rFont->getPage( fontSize ) );
if ( gd ) {
if ( !isMonospace ) {
kerning = font->getKerningFromGlyphIndex(
prevGlyphIndex, curGlyph.codepoint, fontSize, isBold, isItalic,
outlineThickness );
cpos.x += kerning;
width += kerning;
}
drawGlyph( BR, gd, cpos,
fallbacksToColorEmoji &&
Font::isEmojiCodePoint( ch )
? Color::White
: fontColor,
isItalic );
drawGlyph( BR, gd, cpos,
fallbacksToColorEmoji && Font::isEmojiCodePoint( ch )
? Color::White
: fontColor,
isItalic );
Float advance = font->isColorEmojiFont() && ' ' != ch
? gd->getPixelsSize().getWidth()
: gd->getAdvance();
cpos.x += advance;
width += advance;
}
}
if ( ch == ' ' && whitespaceDisplayConfig.spaceDisplayCharacter ) {
if ( spaceGlyph == nullptr ) {
spaceGlyph = font->getGlyphDrawable(
whitespaceDisplayConfig.spaceDisplayCharacter, fontSize );
}
drawGlyph( BR, spaceGlyph, cpos, whitespaceDisplayConfig.color,
isItalic );
}
prevGlyphIndex = curGlyph.codepoint;
}
Float advance = font->isColorEmojiFont() && ' ' != ch
? gd->getPixelsSize().getWidth()
: gd->getAdvance();
cpos.x += advance;
width += advance;
}
}
if ( run.runIsNewLine() ) {
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 );
}
size.x = eemax( width, size.x );
width = 0;
cpos.x = pos.x;
cpos.y += height;
if ( cluster != ssize - 1 )
size.y += height;
}
return true;
} );
prevGlyphIndex = curGlyph.codepoint;
}
if ( run.runIsNewLine() ) {
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 );
}
size.x = eemax( width, size.x );
width = 0;
cpos.x = pos.x;
cpos.y += height;
if ( cluster != ssize - 1 )
size.y += height;
}
return true;
} );
if ( ( style & Text::Underlined ) && width != 0 ) {
_drawUnderline( font, fontSize, fontColor, cpos, style, BR, outlineThickness, pos,
@@ -512,17 +550,26 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
case '\r':
continue;
case '\t': {
Float advance =
font->getGlyph( ' ', fontSize, isBold, isItalic ).advance * tabWidth;
Float advance = hspace * tabWidth;
if ( tabGlyph ) {
drawGlyph( BR, tabGlyph, { cpos.x + tabAlign, cpos.y },
whitespaceDisplayConfig.color, isItalic );
}
width += advance;
cpos.x += advance;
prevChar = ch;
continue;
}
case ' ': {
Float advance = font->getGlyph( ' ', fontSize, isBold, isItalic ).advance;
width += advance;
cpos.x += advance;
if ( whitespaceDisplayConfig.spaceDisplayCharacter ) {
if ( spaceGlyph == nullptr ) {
spaceGlyph = font->getGlyphDrawable(
whitespaceDisplayConfig.spaceDisplayCharacter, fontSize );
}
drawGlyph( BR, spaceGlyph, cpos, whitespaceDisplayConfig.color, isItalic );
}
width += hspace;
cpos.x += hspace;
prevChar = ch;
continue;
}
@@ -598,10 +645,12 @@ Sizef Text::draw( const StringType& string, const Vector2f& pos, Font* font, Flo
template <typename StringType>
Sizef Text::draw( const StringType& string, const Vector2f& pos, const FontStyleConfig& config,
const Uint32& tabWidth, Uint32 textDrawHints ) {
const Uint32& tabWidth, Uint32 textDrawHints,
const WhitespaceDisplayConfig& whitespaceDisplayConfig ) {
return draw<StringType>( string, pos, config.Font, config.CharacterSize, config.FontColor,
config.Style, config.OutlineThickness, config.OutlineColor,
config.ShadowColor, config.ShadowOffset, tabWidth, textDrawHints );
config.ShadowColor, config.ShadowOffset, tabWidth, textDrawHints,
whitespaceDisplayConfig );
}
template <typename StringType>

View File

@@ -326,11 +326,6 @@ void UICodeEditor::draw() {
drawIndentationGuides( lineRange, startScroll, lineHeight );
}
// Draw tab marker
if ( mShowWhitespaces ) {
drawWhitespaces( lineRange, startScroll, lineHeight, visibleLineRange );
}
if ( mShowLineEndings ) {
drawLineEndings( lineRange, startScroll, lineHeight );
}
@@ -1155,6 +1150,8 @@ void UICodeEditor::setCodeEditorFlags( std::string flags, bool enable ) {
mEnableColorPickerOnSelection = enable;
} else if ( "verticalscrollbar" == flag ) {
setVerticalScrollBarEnabled( enable );
} else if ( "horizontalscrollbar" == flag ) {
setHorizontalScrollBarEnabled( enable );
} else if ( "colorpreview" == flag ) {
mColorPreview = enable;
} else if ( "interactivelinks" == flag ) {
@@ -1953,7 +1950,7 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
auto& line = mDoc->line( docLine ).getText();
Float width = 0;
if ( !isMonospaceLine ) {
if ( isNotMonospace() ) {
auto& line = mDoc->line( docLine );
auto found = mLinesWidthCache.find( docLine );
if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first )
@@ -1969,14 +1966,14 @@ Float UICodeEditor::getLineWidth( const Int64& docLine ) {
width = eemax( width, curWidth );
}
if ( !isMonospaceLine ) {
if ( isNotMonospace() ) {
mLinesWidthCache[docLine] = { line.getHash(), width };
}
return width;
}
if ( !isMonospaceLine ) {
if ( isNotMonospace() ) {
auto& line = mDoc->line( docLine );
auto found = mLinesWidthCache.find( docLine );
if ( found != mLinesWidthCache.end() && line.getHash() == found->second.first )
@@ -2008,8 +2005,8 @@ void UICodeEditor::updateScrollBar() {
Float viewPortWidth = getViewportWidth();
mHScrollBar->setPageStep( viewPortWidth / mLongestLineWidth );
mHScrollBar->setClickStep( 0.2f );
bool showHScroll = mLongestLineWidth > viewPortWidth &&
!( mDocView.isWrapEnabled() && mLongestLineWidthDirty );
bool showHScroll = mLongestLineWidth > viewPortWidth && !mDocView.isWrapEnabled() &&
!mLongestLineWidthDirty;
mHScrollBar->setEnabled( showHScroll );
mHScrollBar->setVisible( showHScroll );
}
@@ -3773,6 +3770,10 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
ttf->setEnableFallbackFont( false );
ttf->setEnableEmojiFallback( false );
}
WhitespaceDisplayConfig whitespaceDisplayConfig =
mShowWhitespaces ? WhitespaceDisplayConfig{ L'·', mTabIndentCharacter, mTabIndentAlignment,
Color( mWhitespaceColor ).blendAlpha( mAlpha ) }
: WhitespaceDisplayConfig{};
String::View buff;
Sizef size;
@@ -3854,9 +3855,10 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
}
}
position.x += Text::draw( text, { position.x, position.y + lineOffset },
fontStyle, mTabWidth, drawHints )
.getWidth();
position.x +=
Text::draw( text, { position.x, position.y + lineOffset }, fontStyle,
mTabWidth, drawHints, whitespaceDisplayConfig )
.getWidth();
}
pos += text.size();
@@ -3925,18 +3927,18 @@ void UICodeEditor::drawLineText( const Int64& line, Vector2f position, const Flo
size = Text::draw(
text.substr( start, end ),
{ position.x + start * getGlyphWidth(), position.y + lineOffset },
fontStyle, mTabWidth, drawHints );
fontStyle, mTabWidth, drawHints, whitespaceDisplayConfig );
if ( minimumCharsToCoverScreen == end )
break;
}
} else {
size = Text::draw( text.substr( 0, eemin( curCharsWidth, maxWidth ) ),
{ position.x, position.y + lineOffset }, fontStyle,
mTabWidth, drawHints );
mTabWidth, drawHints, whitespaceDisplayConfig );
}
} else {
size = Text::draw( text, { position.x, position.y + lineOffset }, fontStyle,
mTabWidth, drawHints );
mTabWidth, drawHints, whitespaceDisplayConfig );
}
if ( !isMonospace )

View File

@@ -1427,6 +1427,12 @@ void DebuggerPlugin::drawLineNumbersBefore( UICodeEditor* editor,
Float lineOffset = editor->getLineOffset();
Float offset = editor->getGutterLocalStartOffset( this );
p.setColor( Color( editor->getLineNumberBackgroundColor() ).blendAlpha( editor->getAlpha() ) );
p.drawRectangle( Rectf( { screenStart.x - editor->getPluginsGutterSpace() + offset,
screenStart.y + editor->getPluginsTopSpace() },
Sizef( gutterSpace, editor->getPixelsSize().getHeight() -
editor->getPluginsTopSpace() ) ) );
if ( editor->getDocument().hasFilepath() ) {
auto docIt = mBreakpoints.find( editor->getDocument().getFilePath() );
if ( docIt != mBreakpoints.end() && !docIt->second.empty() ) {