std::string word_wrap_text(const std::string& unwrapped_text, int font_size, int max_width, int max_height, int max_lines, bool partial_line) { VALIDATE(max_width > 0, _("The maximum text width is less than 1.")); utf8::iterator ch(unwrapped_text); std::string current_word; std::string current_line; size_t line_width = 0; size_t current_height = 0; bool line_break = false; bool first = true; bool start_of_line = true; std::string wrapped_text; std::string format_string; SDL_Color color; int font_sz = font_size; int style = TTF_STYLE_NORMAL; utf8::iterator end = utf8::iterator::end(unwrapped_text); while(1) { if(start_of_line) { line_width = 0; format_string.clear(); while(ch != end && *ch < static_cast<ucs4::char_t>(0x100) && is_format_char(*ch) && !ch.next_is_end()) { format_string.append(ch.substr().first, ch.substr().second); ++ch; } // We need to parse the special format characters // to give the proper font_size and style to line_size() font_sz = font_size; style = TTF_STYLE_NORMAL; parse_markup(format_string.begin(),format_string.end(),&font_sz,&color,&style); current_line.clear(); start_of_line = false; } // If there is no current word, get one if(current_word.empty() && ch == end) { break; } else if(current_word.empty()) { if(*ch == ' ' || *ch == '\n') { current_word = *ch; ++ch; } else { ucs4::char_t previous = 0; for(;ch != utf8::iterator::end(unwrapped_text) && *ch != ' ' && *ch != '\n'; ++ch) { if(!current_word.empty() && break_before(*ch) && !no_break_after(previous)) break; if(!current_word.empty() && break_after(previous) && !no_break_before(*ch)) break; current_word.append(ch.substr().first, ch.substr().second); previous = *ch; } } } if(current_word == "\n") { line_break = true; current_word.clear(); start_of_line = true; } else { const size_t word_width = line_size(current_word, font_sz, style).w; line_width += word_width; if(static_cast<long>(line_width) > max_width) { if (!partial_line && static_cast<long>(word_width) > max_width) { cut_word(current_line, current_word, font_sz, style, max_width); } if(current_word == " ") current_word = ""; line_break = true; } else { current_line += current_word; current_word = ""; } } if(line_break || (current_word.empty() && ch == end)) { SDL_Rect size = line_size(current_line, font_sz, style); if(max_height > 0 && current_height + size.h >= size_t(max_height)) { return wrapped_text; } if(!first) { wrapped_text += '\n'; } wrapped_text += format_string + current_line; current_line.clear(); line_width = 0; current_height += size.h; line_break = false; first = false; if(--max_lines == 0) { return wrapped_text; } } } return wrapped_text; }
pxTextWrapperBase& pxTextWrapperBase::Wrap( const wxWindow& win, const wxString& text, int widthMax ) { if( text.IsEmpty() ) return *this; const wxChar *lastSpace = NULL; bool wasWrapped = false; wxString line; line.Alloc( text.Length()+12 ); const wxChar* lineStart = text.wc_str(); for ( const wxChar *p = lineStart; ; p++ ) { if ( IsStartOfNewLine() ) { OnNewLine(); lastSpace = NULL; lineStart = p; if(wasWrapped) line = m_indent; else line.clear(); } if ( *p == L'\n' || *p == L'\0' ) { wasWrapped = false; DoOutputLine(line); if ( *p == L'\0' ) break; } else // not EOL { if (is_cjk_char(*p)) { if (!no_break_before(*p)) { if (p == lineStart || !no_break_after(*(p-1))) lastSpace = p; } } else if ( *p == L' ' || *p == L',' || *p == L'/' ) lastSpace = p; line += *p; if ( widthMax >= 0 && lastSpace ) { int width; win.GetTextExtent(line, &width, NULL); if ( width > widthMax ) { wasWrapped = true; // remove the last word from this line line.erase(lastSpace - lineStart, p + 1 - lineStart); DoOutputLine(line); // go back to the last word of this line which we didn't // output yet p = lastSpace; if ( *p != L' ' ) p--; } } //else: no wrapping at all or impossible to wrap } } return *this; }