You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
4.1 KiB

// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2020 Intel Corporation. All Rights Reserved.
#include <string>
#include <vector>
#include <sstream>
#include "wrap.h"
#include <rsutils/string/split.h>
#include <third-party/imgui/imgui.h>
namespace utilities {
namespace imgui {
void trim_leading_spaces( std::string &remaining_paragraph )
{
auto non_space_index = remaining_paragraph.find_first_not_of( ' ' );
if( non_space_index != std::string::npos )
{
// Remove trailing spaces
remaining_paragraph = remaining_paragraph.substr( non_space_index );
}
}
std::string wrap_paragraph( const std::string & paragraph, int wrap_pixels_width )
{
float space_width = ImGui::CalcTextSize( " " ).x; // Calculate space width in pixels
std::string wrapped_line; // The line that is wrapped in this iteration
std::string wrapped_paragraph; // The output wrapped paragraph
auto remaining_paragraph
= paragraph; // Holds the remaining unwrapped part of the input paragraph
// Handle a case when the paragraph starts with spaces
trim_leading_spaces(remaining_paragraph);
auto next_word = remaining_paragraph.substr(
0,
remaining_paragraph.find( ' ' ) ); // The next word to add to the current line
bool first_word = true;
while( ! next_word.empty() )
{
float next_x = 0.0f;
// If this is the first word we try to place it first in line,
// if not we concatenate it to the last word after adding a space
if( ! first_word )
{
next_x = ImGui::CalcTextSize( wrapped_line.c_str() ).x + space_width;
}
if( next_x + ImGui::CalcTextSize( next_word.c_str() ).x <= wrap_pixels_width )
{
if( ! first_word )
wrapped_line += " "; // First word should not start with " "
wrapped_line += next_word;
}
else
{ // Current line cannot feat new word so we wrap the line and
// start building the new line
wrapped_paragraph += wrapped_line; // copy line build by now
if( ! first_word )
wrapped_paragraph += '\n'; // break the previous line if exist
wrapped_line = next_word; // add next work to new line
}
first_word = false;
// If we have more characters left other then the current word, prepare inputs for next
// iteration, If not add the current line built so far to the output and finish current
// line wrap.
if( remaining_paragraph.size() > next_word.size() )
{
remaining_paragraph = remaining_paragraph.substr( next_word.size() + 1 );
// Handle a case when the paragraph starts with spaces
trim_leading_spaces(remaining_paragraph);
next_word = remaining_paragraph.substr( 0, remaining_paragraph.find( ' ' ) );
// If no more words exist, copy the current wrapped line to output and stop
if( next_word.empty() )
{
wrapped_paragraph += wrapped_line;
break;
}
}
else
{
wrapped_paragraph += wrapped_line;
break;
}
}
return wrapped_paragraph;
}
std::string wrap( const std::string & text, int wrap_pixels_width )
{
// Do not wrap if the wrap is smaller then 32 pixels (~2 characters on font 16)
if( wrap_pixels_width < 32 )
return text;
// Split text into paragraphs
auto paragraphs_vector = rsutils::string::split( text, '\n' );
std::string wrapped_text;
size_t line_number = 1;
// Wrap each line according to the requested wrap width
for( auto paragraph : paragraphs_vector )
{
wrapped_text += wrap_paragraph( paragraph, wrap_pixels_width );
// Each paragraph except the last one ends with a new line
if( line_number++ != paragraphs_vector.size() )
wrapped_text += '\n';
}
return wrapped_text;
}
} // namespace imgui
} // namespace utilities