tBane Temat założony przez niniejszego użytkownika |
[SFML 2.X] Wrapper tekstu - dzieleniu tekstu na linie » 2025-04-22 16:17:42 Witam. Mam algorytm na dzielenie tekstu ale nie działa dobrze z tekstem "test\ntest". Algorytm pomija ostatnią linię. ChatGPT nie pomógł ... :-/ Chodzi o to by podzielić tekst na linie o określonej długości z uwzględnieniem enterów.
std::vector < std::wstring > wrapText( std::wstring text, const sf::Font & font, short characterSize, short maxWidth ) { std::vector < std::wstring > wrappedText; std::wistringstream wordsStream( text ); std::wstring word; std::wstring currentLine; while( std::getline( wordsStream, word, L' ' ) ) { std::size_t newLinePos; while(( newLinePos = word.find( L'\n' ) ) != std::wstring::npos ) { std::wstring beforeNewLine = word.substr( 0, newLinePos ); std::wstring testLine =( currentLine.empty() ) ? beforeNewLine : currentLine + L" " + beforeNewLine; sf::Text testText( testLine, font, characterSize ); if( !testLine.empty() && testText.getLocalBounds().width >= maxWidth ) { wrappedText.push_back( currentLine ); currentLine = beforeNewLine; } else { currentLine = testLine; } wrappedText.push_back( currentLine ); currentLine.clear(); word = word.substr( newLinePos + 1 ); } std::wstring testLine =( currentLine.empty() ) ? word : currentLine + L" " + word; sf::Text testText( testLine, font, characterSize ); if( maxWidth > 0.0f && testText.getLocalBounds().width >= maxWidth ) { wrappedText.push_back( currentLine ); currentLine = word; } else { currentLine = testLine; } } if( !currentLine.empty() ) { wrappedText.push_back( currentLine ); } if( wrappedText.size() == 0 ) wrappedText.push_back( L"" ); return wrappedText; }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-04-22 18:03:26 Ok mocno pomęczyłem ChatGPT z Deep research i się udało.. Oto kod. Niech Wam służy :-) std::vector < std::wstring > wrapText( std::wstring text, const sf::Font & font, short characterSize, short maxWidth ) { std::vector < std::wstring > result; std::wistringstream lineStream( text ); std::wstring paragraph; std::wstring currentLine; while( std::getline( lineStream, paragraph, L'\n' ) ) { std::wistringstream wordStream( paragraph ); std::wstring word; while( wordStream >> word ) { std::wstring testLine = currentLine.empty() ? word : currentLine + L" " + word; if( maxWidth > 0 ) { sf::Text sfText( testLine, font, characterSize ); float width = sfText.getLocalBounds().width; if( width > maxWidth ) { if( !currentLine.empty() ) { result.push_back( currentLine ); currentLine = word; } else { result.push_back( word ); currentLine.clear(); } } else { currentLine = testLine; } } else { currentLine = testLine; } } result.push_back( currentLine ); currentLine.clear(); } if( !currentLine.empty() ) { result.push_back( currentLine ); } if( !text.empty() && text.back() == L'\n' ) { result.push_back( L"" ); } if( result.empty() ) { result.push_back( L"" ); } return result; }
|
|
nanoant20 |
» 2025-04-22 20:18:32 well done. widać, że zależy Ci na jakości i detalu, skorzystałem z Twojej hojności |
|
pekfos |
» 2025-04-22 23:15:15 result.push_back( currentLine ); currentLine.clear(); Nie kończy się spacją nigdy, wynika z konstrukcji wartości currentLine. Natomiast dodanie pustej linii jest dziwnym wyborem, bo to tak nigdy nie działa. Gdy masz dwa paragrafy podzielone na kilka linii przez ograniczenie szerokości, nie ma takiej magicznej szerokości okna przy której pojawi się pusta linia między nimi. if( !currentLine.empty() ) { result.push_back( currentLine ); } Ten warunek jest zawsze fałszywy. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-04-22 23:32:51 Ale algorytm działa dla wszystkich przypadków... i działa w Edytorze |
|
nanoant20 |
» 2025-04-23 09:04:40 @tBane tam gdzie @pekfos pisze że warunek if( !currentLine.empty() ) jest zawsze fałszywy możesz usunąć. Dla tego przypadku "test\n test" gdzie zaczyna się od spacji też nie działa. Dobrze by było dodać logikę obsługę białych znaków spacji czy tabulatorów |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-04-23 09:40:17 Jak usunę ten warunek to doda mi pustą linię ... ale faktycznie ze spacją na początku nie działa. Nie wiem jak to naprawić. |
|
nanoant20 |
» 2025-04-23 15:49:30 do sprawdzenia, funkcja std::vector<std::wstring> wrapText przebudowana przez copilot.microsoft.com copilot Funkcja wrapText dzieli tekst na linie, starając się, aby szerokość każdej linii nie przekraczała maxWidth. Zachowuje również początkowe spacje (indent - wcięcie) w akapitach. #include <SFML/Graphics.hpp> #include <iostream> #include <vector> #include <string> #include <locale> #include <codecvt> #include <sstream> std::vector < std::wstring > wrapText( const std::wstring & text, const sf::Font & font, short characterSize, short maxWidth ) { std::vector < std::wstring > result; std::wistringstream lineStream( text ); std::wstring paragraph; while( std::getline( lineStream, paragraph, L'\n' ) ) { std::wstring currentLine; if( !paragraph.empty() && paragraph[ 0 ] == L' ' ) { size_t firstNonSpace = paragraph.find_first_not_of( L' ' ); if( firstNonSpace == std::wstring::npos ) { result.push_back( paragraph ); continue; } currentLine = paragraph.substr( 0, firstNonSpace ); paragraph = paragraph.substr( firstNonSpace ); } if( paragraph.empty() ) { result.push_back( currentLine ); continue; } std::wistringstream wordStream( paragraph ); std::wstring word; while( wordStream >> word ) { std::wstring testLine; if( currentLine.empty() ) testLine = word; else { if( currentLine.back() == L' ' ) testLine = currentLine + word; else testLine = currentLine + L" " + word; } if( maxWidth > 0 ) { sf::Text sfText( testLine, font, characterSize ); float width = sfText.getLocalBounds().width; if( width > maxWidth ) { if( !currentLine.empty() ) { result.push_back( currentLine ); currentLine = word; } else { result.push_back( word ); currentLine.clear(); } } else { currentLine = testLine; } } else { currentLine = testLine; } } result.push_back( currentLine ); currentLine.clear(); } if( !text.empty() && text.back() == L'\n' ) { result.push_back( L"" ); } if( result.empty() ) { result.push_back( L"" ); } return result; }
int main() { std::setlocale( LC_ALL, "pl_PL.UTF-8" ); sf::RenderWindow app( sf::VideoMode( 300, 620 ), "Text Wrapping" ); sf::Font font; if( !font.loadFromFile( "arial.ttf" ) ) { std::cout << "Nie udało się załadować czcionki!" << std::endl; return - 1; } short characterSize = 24; short maxWidth = 200; sf::Text sfText; sfText.setFont( font ); sfText.setCharacterSize( characterSize ); sfText.setFillColor( sf::Color::White ); std::vector < std::wstring > TestText = { L"Apetyt rośnie w miarę jedzenia.", L"", L"Bez pracy nie ma kołaczy.\n" L"test\n test\n test", L" ", L"Audaces fortuna iuvat – Odważnym szczęście sprzyja", L"\n ęóąśłżźćń \n ĘÓĄŚŁŻŹĆŃ" }; std::vector < std::wstring > wrappedText; for( const auto & text: TestText ) { auto wrappedLines = wrapText( text, font, characterSize, maxWidth ); wrappedText.insert( wrappedText.end(), wrappedLines.begin(), wrappedLines.end() ); } while( app.isOpen() ) { float xPosition = 25.0f; float yPosition = 20.0f; sf::Event event; while( app.pollEvent( event ) ) { if( event.type == sf::Event::Closed ) app.close(); } app.clear( sf::Color::Black ); for( const auto & line: wrappedText ) { sfText.setString( line ); sfText.setPosition( xPosition, yPosition ); app.draw( sfText ); yPosition += characterSize + 5; } app.display(); } return 0; }
|
|
« 1 » 2 |