diff options
Diffstat (limited to 'indra/llui/lltextbase.cpp')
-rw-r--r-- | indra/llui/lltextbase.cpp | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 20be739286..c570285856 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1505,8 +1505,8 @@ void LLTextBase::reflow() segment_set_t::iterator seg_iter = mSegments.begin(); S32 seg_offset = 0; S32 line_start_index = 0; - const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin - S32 remaining_pixels = text_available_width; + const F32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin + F32 remaining_pixels = text_available_width; S32 line_count = 0; // find and erase line info structs starting at start_index and going to end of document @@ -1522,6 +1522,7 @@ void LLTextBase::reflow() } S32 line_height = 0; + S32 seg_line_offset = line_count + 1; while(seg_iter != mSegments.end()) { @@ -1531,13 +1532,15 @@ void LLTextBase::reflow() S32 cur_index = segment->getStart() + seg_offset; // ask segment how many character fit in remaining space - S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX, + S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, ll_round(remaining_pixels)) : S32_MAX, seg_offset, cur_index - line_start_index, - S32_MAX); + S32_MAX, + line_count - seg_line_offset); - S32 segment_width, segment_height; - bool force_newline = segment->getDimensions(seg_offset, character_count, segment_width, segment_height); + F32 segment_width; + S32 segment_height; + bool force_newline = segment->getDimensionsF32(seg_offset, character_count, segment_width, segment_height); // grow line height as necessary based on reported height of this segment line_height = llmax(line_height, segment_height); remaining_pixels -= segment_width; @@ -1546,11 +1549,13 @@ void LLTextBase::reflow() S32 last_segment_char_on_line = segment->getStart() + seg_offset; - S32 text_actual_width = text_available_width - remaining_pixels; + // Note: make sure text will fit in width - use ceil, but also make sure + // ceil is used only once per line + S32 text_actual_width = llceil(text_available_width - remaining_pixels); S32 text_left = getLeftOffset(text_actual_width); LLRect line_rect(text_left, cur_top, - text_left + text_actual_width, + text_left + text_actual_width, cur_top - line_height); // if we didn't finish the current segment... @@ -1597,6 +1602,7 @@ void LLTextBase::reflow() } ++seg_iter; seg_offset = 0; + seg_line_offset = force_newline ? line_count + 1 : line_count; } if (force_newline) { @@ -3063,9 +3069,17 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc LLTextSegment::~LLTextSegment() {} -bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const { width = 0; height = 0; return false;} +bool LLTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = 0; return false; } +bool LLTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +{ + F32 fwidth = 0; + bool result = getDimensionsF32(first_char, num_chars, fwidth, height); + width = ll_round(fwidth); + return result; +} + S32 LLTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const { return 0; } -S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const { return 0; } +S32 LLTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { return 0; } void LLTextSegment::updateLayout(const LLTextBase& editor) {} F32 LLTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRectf& draw_rect) { return draw_rect.mLeft; } bool LLTextSegment::canEdit() const { return false; } @@ -3311,7 +3325,7 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip) mTooltip = tooltip; } -bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { height = 0; width = 0; @@ -3320,7 +3334,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt height = mFontHeight; const LLWString &text = getWText(); // if last character is a newline, then return true, forcing line break - width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars); + width = mStyle->getFont()->getWidthF32(text.c_str(), mStart + first_char, num_chars); } return false; } @@ -3335,7 +3349,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, round); } -S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { const LLWString &text = getWText(); @@ -3352,7 +3366,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin // if no character yet displayed on this line, don't require word wrapping since // we can just move to the next line, otherwise insist on it so we make forward progress - LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0) + LLFontGL::EWordWrapStyle word_wrap_style = (line_offset == 0) ? LLFontGL::WORD_BOUNDARY_IF_POSSIBLE : LLFontGL::ONLY_WORD_BOUNDARIES; @@ -3488,14 +3502,28 @@ LLInlineViewSegment::~LLInlineViewSegment() mView->die(); } -bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { - if (first_char == 0 && num_chars == 0) + if (first_char == 0 && num_chars == 0) { - // we didn't fit on a line, the widget will fall on the next line - // so dimensions here are 0 + // We didn't fit on a line or were forced to new string + // the widget will fall on the next line, so width here is 0 width = 0; - height = 0; + + if (mForceNewLine) + { + // Chat, string can't be smaller then font height even if it is empty + LLStyleSP s(new LLStyle(LLStyle::Params().visible(true))); + height = s->getFont()->getLineHeight(); + + return true; // new line + } + else + { + // height from previous segment in same string will be used, word-wrap + height = 0; + } + } else { @@ -3506,13 +3534,16 @@ bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt return false; } -S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { // if putting a widget anywhere but at the beginning of a line // and the widget doesn't fit or mForceNewLine is true // then return 0 chars for that line, and all characters for the next - if (line_offset != 0 - && (mForceNewLine || num_pixels < mView->getRect().getWidth())) + if (mForceNewLine && line_ind == 0) + { + return 0; + } + else if (line_offset != 0 && num_pixels < mView->getRect().getWidth()) { return 0; } @@ -3558,14 +3589,14 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLT LLLineBreakTextSegment::~LLLineBreakTextSegment() { } -bool LLLineBreakTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLLineBreakTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = mFontHeight; return true; } -S32 LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +S32 LLLineBreakTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { return 1; } @@ -3587,7 +3618,7 @@ LLImageTextSegment::~LLImageTextSegment() static const S32 IMAGE_HPAD = 3; -bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const +bool LLImageTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const { width = 0; height = mStyle->getFont()->getLineHeight(); @@ -3601,7 +3632,7 @@ bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width return false; } -S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const +S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars, S32 line_ind) const { LLUIImagePtr image = mStyle->getImage(); |