aboutsummaryrefslogtreecommitdiff
path: root/dw/textblock_linebreaking.cc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2014-03-30 13:51:43 +0200
committerSebastian Geerken <devnull@localhost>2014-03-30 13:51:43 +0200
commit4184225ff4fb71cc4cef003f18b85f1f949e115a (patch)
tree288d553f509bcfde3014209c5f6dfc7ee1eb9d00 /dw/textblock_linebreaking.cc
parent8cd77958f064fa2ef4463f5984faaee0567b5d6d (diff)
Finished float positioning iteration.
Diffstat (limited to 'dw/textblock_linebreaking.cc')
-rw-r--r--dw/textblock_linebreaking.cc84
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 ();