diff options
author | Sebastian Geerken <devnull@localhost> | 2014-03-30 13:51:43 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-03-30 13:51:43 +0200 |
commit | 4184225ff4fb71cc4cef003f18b85f1f949e115a (patch) | |
tree | 288d553f509bcfde3014209c5f6dfc7ee1eb9d00 | |
parent | 8cd77958f064fa2ef4463f5984faaee0567b5d6d (diff) |
Finished float positioning iteration.
-rw-r--r-- | dw/textblock_linebreaking.cc | 84 |
1 files changed, 63 insertions, 21 deletions
diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index e38d5377..44f7c2dc 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -619,8 +619,7 @@ bool Textblock::wrapWordInFlow (int wordIndex, bool wrapAll) bool regardBorder = mustBorderBeRegarded (lines->size ()); bool thereWillBeMoreSpace = regardBorder ? - newLineHasFloatLeft || newLineHasFloatRight : - false; + newLineHasFloatLeft || newLineHasFloatRight : false; DBG_OBJ_MSGF ("construct.word", 1, "thereWillBeMoreSpace = %s ? %s || %s : false = %s", @@ -740,6 +739,7 @@ bool Textblock::wrapWordInFlow (int wordIndex, bool wrapAll) int startSearch = misc::max (firstIndex, lastFloatPos + 1); int newFloatPos = -1; + // Step 1: search for the next float. DBG_OBJ_MSGF ("construct.word", 2, "searching from %d to %d", startSearch, breakPos); for (int i = startSearch; newFloatPos == -1 && i <= breakPos; i++) { @@ -759,30 +759,72 @@ bool Textblock::wrapWordInFlow (int wordIndex, bool wrapAll) if (newFloatPos == -1) floatHandled = false; else { + // Step 2: position the float and re-calculate the line. lastFloatPos = newFloatPos; containingBlock->outOfFlowMgr->tellPosition (words->getRef(lastFloatPos)->content.widget, yNewLine); - calcBorders (lastFloatPos, height); - bool thereWillBeMoreSpace = regardBorder ? - newLineHasFloatLeft || newLineHasFloatRight : - false; - - DBG_OBJ_MSGF ("construct.word", 2, "thereWillBeMoreSpace = %s", - thereWillBeMoreSpace ? "true" : "false"); - - for(int i = firstIndex; i <= wordIndexEnd; i++) - accumulateWordData (i); - - breakPos = - searchBreakPos (wordIndex, firstIndex, &searchUntil, - tempNewLine, penaltyIndex, - thereWillBeMoreSpace, wrapAll, - &wordListChanged, &wordIndexEnd); - height = calcLinePartHeight (firstIndex, breakPos); - - // TODO: Iterate until the height converges? + // The height of this part of the line (until the new + // break position) may change with the break position, + // but the break position may depend on the height. We + // try to let these values converge. + // + // The height, as a function of the break position, is + // monotonically (but not strictly) increasing, since + // more words may make the line higher (but not + // flatter). The break position, as a function of the + // height, is, however, monotonically (but not + // strictly) *de*creasing, since flatter lines may fit + // easier between floats (although this is a rare + // case). So a convergence is not necessary. + // + // For this reason, we iterate only as long as the + // height does not increase again, and stop if it + // remains the same. As the minimum is 1, this approach + // will force the iteration to stop. + // + // (As a side effect, this will lead to a larger break + // position, and so place as much words as possible in + // the line.) + + bool firstRun = true; + while (true) { + calcBorders (lastFloatPos, height); + thereWillBeMoreSpace = regardBorder ? + newLineHasFloatLeft || newLineHasFloatRight : false; + + DBG_OBJ_MSGF ("construct.word", 2, + "thereWillBeMoreSpace = %s", + thereWillBeMoreSpace ? "true" : "false"); + + for(int i = firstIndex; i <= wordIndexEnd; i++) + accumulateWordData (i); + + int newBreakPos = + searchBreakPos (wordIndex, firstIndex, &searchUntil, + tempNewLine, penaltyIndex, + thereWillBeMoreSpace, wrapAll, + &wordListChanged, &wordIndexEnd); + int newHeight = calcLinePartHeight (firstIndex, newBreakPos); + + if (!firstRun && newHeight >= height) + // - newHeight > height: do not proceed, discard + // new values, which are less desirable than + // the old ones (see above). + // - newHeight == height: convergence, stop + // here. New values can be discarded, since + // they are the same. + // (Since *some* value are needed, the results + // from the first run are never discarded.) + break; + else { + height = newHeight; + breakPos = newBreakPos; + } + + firstRun = false; + } } DBG_OBJ_MSG_END (); |