From 5aeb0b1acfa750df074b77f909200723d618bbe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 25 Jul 2026 20:41:35 -0300 Subject: [PATCH] The new sparse invariant is: - Empty vector: every quad is Mask; use the existing single draw call. - Non-empty vector: the text contains subpixel glyphs; entries correspond to every quad. addGlyphQuad() therefore delays allocation until the first subpixel glyph. At that point it backfills earlier quads as Mask, records the current subpixel glyph, and tracks every subsequent quad. addLine() only appends Mask after tracking has started. A line before the first subpixel glyph will be included by the later backfill; a line after it must be appended to preserve the one-entry-per-quad mapping. This protects the common grayscale path from subpixel-related overhead while correctly handling mixed mask/subpixel text. It introduces no allocations until subpixel rendering is actually encountered. The critical fix versus the earlier broken version is that the first subpixel glyph is appended unconditionally. The old code accidentally skipped it when it was the first quad, causing the first character to be classified as Mask. --- src/eepp/graphics/text.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp index de2a820e3..277f927f5 100644 --- a/src/eepp/graphics/text.cpp +++ b/src/eepp/graphics/text.cpp @@ -1732,8 +1732,7 @@ void Text::draw( const Float& X, const Float& Y, const Vector2f& scale, const Fl return; unsigned int numvert = mVertices.size(); - const bool containsSubpixel = std::find( mRenderModes.begin(), mRenderModes.end(), - GlyphRenderMode::Subpixel ) != mRenderModes.end(); + const bool containsSubpixel = !mRenderModes.empty(); const Float drawX = containsSubpixel && rotation == 0.f && scale == 1.f ? std::trunc( X ) : X; const Float drawY = containsSubpixel && rotation == 0.f && scale == 1.f ? std::trunc( Y ) : Y; @@ -2682,8 +2681,9 @@ void Text::setFillColor( const std::vector& colors ) { // Add an underline or strikethrough line to the vertex array void Text::addLine( std::vector& vertices, Float lineLength, Float lineTop, Float offset, Float thickness, Float outlineThickness, Int32 centerDiffX ) { - ( &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes ) - .push_back( GlyphRenderMode::Mask ); + auto& renderModes = &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes; + if ( !renderModes.empty() ) + renderModes.push_back( GlyphRenderMode::Mask ); Float top = std::floor( lineTop + offset - ( thickness / 2 ) + 0.5f ); Float bottom = top + std::floor( thickness + 0.5f ); Float u1 = 0; @@ -2759,8 +2759,14 @@ void Text::addLine( std::vector& vertices, Float lineLength, Float void Text::addGlyphQuad( std::vector& vertices, Vector2f position, const EE::Graphics::Glyph& glyph, Float italic, Float outlineThickness, Int32 centerDiffX ) { - ( &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes ) - .push_back( glyph.renderMode ); + auto& renderModes = &vertices == &mOutlineVertices ? mOutlineRenderModes : mRenderModes; + if ( glyph.renderMode == GlyphRenderMode::Subpixel ) { + if ( renderModes.empty() ) + renderModes.resize( vertices.size() / GLi->quadVertex(), GlyphRenderMode::Mask ); + renderModes.push_back( GlyphRenderMode::Subpixel ); + } else if ( !renderModes.empty() ) { + renderModes.push_back( GlyphRenderMode::Mask ); + } if ( glyph.renderMode == GlyphRenderMode::Subpixel ) position = position.trunc(); Float padding = 1.0;