diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 3b1d40fc3..c9cfc8c2c 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -195,8 +195,20 @@ struct TypesetBookImpl : TypesetBook struct TypesetBookImpl::Typesetter : BookTypesetter { + struct PartialText { + StyleImpl *mStyle; + Utf8Stream::Point mBegin; + Utf8Stream::Point mEnd; + int mWidth; + + PartialText( StyleImpl *style, Utf8Stream::Point begin, Utf8Stream::Point end, int width) : + mStyle(style), mBegin(begin), mEnd(end), mWidth(width) + {} + }; + typedef TypesetBookImpl Book; typedef boost::shared_ptr BookPtr; + typedef std::vector::const_iterator PartialTextConstIterator; int mPageWidth; int mPageHeight; @@ -207,6 +219,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter Run * mRun; std::vector mSectionAlignment; + std::vector mPartialWhitespace; + std::vector mPartialWord; Book::Content const * mCurrentContent; Alignment mCurrentAlignment; @@ -273,6 +287,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter intptr_t addContent (Utf8Span text, bool select) { + add_partial_text(); + Contents::iterator i = mBook->mContents.insert (mBook->mContents.end (), Content (text.first, text.second)); if (select) @@ -283,6 +299,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter void selectContent (intptr_t contentHandle) { + add_partial_text(); + mCurrentContent = reinterpret_cast (contentHandle); } @@ -302,12 +320,16 @@ struct TypesetBookImpl::Typesetter : BookTypesetter { assert (margin == 0); //TODO: figure out proper behavior here... + add_partial_text(); + mRun = NULL; mLine = NULL; } void sectionBreak (float margin) { + add_partial_text(); + if (mBook->mSections.size () > 0) { mRun = NULL; @@ -321,6 +343,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter void setSectionAlignment (Alignment sectionAlignment) { + add_partial_text(); + if (mSection != NULL) mSectionAlignment.back () = sectionAlignment; mCurrentAlignment = sectionAlignment; @@ -331,6 +355,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter int curPageStart = 0; int curPageStop = 0; + add_partial_text(); + std::vector ::iterator sa = mSectionAlignment.begin (); for (Sections::iterator i = mBook->mSections.begin (); i != mBook->mSections.end (); ++i, ++sa) { @@ -415,23 +441,23 @@ struct TypesetBookImpl::Typesetter : BookTypesetter void writeImpl (StyleImpl * style, Utf8Stream::Point _begin, Utf8Stream::Point _end) { - int line_height = style->mFont->getDefaultHeight (); - Utf8Stream stream (_begin, _end); while (!stream.eof ()) { if (ucsLineBreak (stream.peek ())) { + add_partial_text(); stream.consume (); mLine = NULL, mRun = NULL; continue; } + if (ucsBreakingSpace (stream.peek ()) && !mPartialWord.empty()) + add_partial_text(); + int word_width = 0; - int word_height = 0; int space_width = 0; - int character_count = 0; Utf8Stream::Point lead = stream.current (); @@ -450,8 +476,6 @@ struct TypesetBookImpl::Typesetter : BookTypesetter MyGUI::GlyphInfo* gi = style->mFont->getGlyphInfo (stream.peek ()); if (gi) word_width += gi->advance + gi->bearingX; - word_height = line_height; - ++character_count; stream.consume (); } @@ -460,21 +484,57 @@ struct TypesetBookImpl::Typesetter : BookTypesetter if (lead == extent) break; - int left = mLine ? mLine->mRect.right : 0; + if ( lead != origin ) + mPartialWhitespace.push_back (PartialText (style, lead, origin, space_width)); + if ( origin != extent ) + mPartialWord.push_back (PartialText (style, origin, extent, word_width)); + } + } - if (left + space_width + word_width > mPageWidth) - { - mLine = NULL, mRun = NULL; + void add_partial_text () + { + if (mPartialWhitespace.empty() && mPartialWord.empty()) + return; - append_run (style, origin, extent, extent - origin, word_width, mBook->mRect.bottom + word_height); - } - else + int space_width = 0; + int word_width = 0; + + for (PartialTextConstIterator i = mPartialWhitespace.begin (); i != mPartialWhitespace.end (); ++i) + space_width += i->mWidth; + for (PartialTextConstIterator i = mPartialWord.begin (); i != mPartialWord.end (); ++i) + word_width += i->mWidth; + + int left = mLine ? mLine->mRect.right : 0; + + if (left + space_width + word_width > mPageWidth) + { + mLine = NULL, mRun = NULL, left = 0; + } + else + { + for (PartialTextConstIterator i = mPartialWhitespace.begin (); i != mPartialWhitespace.end (); ++i) { int top = mLine ? mLine->mRect.top : mBook->mRect.bottom; + int line_height = i->mStyle->mFont->getDefaultHeight (); + + append_run ( i->mStyle, i->mBegin, i->mEnd, 0, left + i->mWidth, top + line_height); - append_run (style, lead, extent, extent - origin, left + space_width + word_width, top + word_height); + left = mLine->mRect.right; } } + + for (PartialTextConstIterator i = mPartialWord.begin (); i != mPartialWord.end (); ++i) + { + int top = mLine ? mLine->mRect.top : mBook->mRect.bottom; + int line_height = i->mStyle->mFont->getDefaultHeight (); + + append_run (i->mStyle, i->mBegin, i->mEnd, i->mEnd - i->mBegin, left + i->mWidth, top + line_height); + + left = mLine->mRect.right; + } + + mPartialWhitespace.clear(); + mPartialWord.clear(); } void append_run (StyleImpl * style, Utf8Stream::Point begin, Utf8Stream::Point end, int pc, int right, int bottom)