示例#1
0
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;
}
示例#2
0
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;
}