aboutsummaryrefslogtreecommitdiff
path: root/dw
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2014-10-15 00:00:08 +0200
committerSebastian Geerken <devnull@localhost>2014-10-15 00:00:08 +0200
commit021d425fea3bdc727328ccbe24f508453a4ada36 (patch)
tree8a3e9c11bfb4672c79e9ef797daccca6ca4102fd /dw
parent6c5f32b8ec8f9a01ca0ab6107779bfa2eda5299b (diff)
parent3143688e32d73fa788fd2d37e395753bae578e7d (diff)
Merge with main repo.
Diffstat (limited to 'dw')
-rw-r--r--dw/textblock.cc262
-rw-r--r--dw/textblock.hh110
-rw-r--r--dw/textblock_iterator.cc2
-rw-r--r--dw/textblock_linebreaking.cc111
4 files changed, 265 insertions, 220 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc
index ae4c6cb4..92d7f662 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -83,7 +83,7 @@ void Textblock::WordImgRenderer::getBgArea (int *x, int *y, int *width,
*x = textblock->allocation.x + this->xWordWidget;
*y = textblock->lineYOffsetCanvas (line);
*width = textblock->words->getRef(wordNo)->size.width;
- *height = line->boxAscent + line->boxDescent;
+ *height = line->borderAscent + line->borderDescent;
}
void Textblock::WordImgRenderer::getRefArea (int *xRef, int *yRef,
@@ -330,40 +330,40 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
showMissingLines ();
if (lines->size () > 0) {
- Line *lastLine = lines->getRef (lines->size () - 1);
- requisition->width = lastLine->maxLineWidth;
-
- DBG_OBJ_MSGF ("resize", 1, "lines[%d]->maxLineWidth = %d",
- lines->size () - 1, lastLine->maxLineWidth);
-
- DBG_OBJ_MSGF ("resize", 1, "lines[0]->boxAscent = %d",
- lines->getRef(0)->boxAscent);
- DBG_OBJ_MSGF ("resize", 1, "lines[%d]->top = %d",
- lines->size () - 1, lastLine->top);
- DBG_OBJ_MSGF ("resize", 1, "lines[%d]->boxAscent = %d",
- lines->size () - 1, lastLine->boxAscent);
- DBG_OBJ_MSGF ("resize", 1, "lines[%d]->boxDescent = %d",
- lines->size () - 1, lastLine->boxDescent);
-
- /* Note: the breakSpace of the last line is ignored, so breaks
- at the end of a textblock are not visible. */
- requisition->ascent = lines->getRef(0)->boxAscent;
- requisition->descent = lastLine->top
- + lastLine->boxAscent + lastLine->boxDescent -
- lines->getRef(0)->boxAscent;
+ Line *firstLine = lines->getRef(0), *lastLine = lines->getLastRef ();
+
+ // Note: the breakSpace of the last line is ignored, so breaks
+ // at the end of a textblock are not visible.
+
+ requisition->width =
+ lastLine->maxLineWidth + leftInnerPadding + boxDiffWidth ();
+
+ // Also regard collapsing of this widget top margin and the top
+ // margin of the first line box:
+ requisition->ascent = calcVerticalBorder (getStyle()->padding.top,
+ getStyle()->borderWidth.top,
+ getStyle()->margin.top
+ + extraSpace.top,
+ firstLine->borderAscent,
+ firstLine->marginAscent);
+
+ // And here, regard collapsing of this widget bottom margin and the
+ // bottom margin of the last line box:
+ requisition->descent =
+ // (BTW, this line:
+ lastLine->top - firstLine->borderAscent + lastLine->borderAscent +
+ // ... is 0 for a block with one line, so special handling
+ // for this case is not necessary.)
+ calcVerticalBorder (getStyle()->padding.bottom,
+ getStyle()->borderWidth.bottom,
+ getStyle()->margin.bottom + extraSpace.bottom,
+ lastLine->borderDescent, lastLine->marginDescent);
} else {
- requisition->width = 0; // before: lastLineWidth;
- requisition->ascent = 0;
- requisition->descent = 0;
+ requisition->width = leftInnerPadding + boxDiffWidth ();
+ requisition->ascent = boxOffsetY ();
+ requisition->descent = boxRestHeight ();;
}
- DBG_OBJ_MSGF ("resize", 1, "left inner padding = %d, boxDiffWidth = %d",
- leftInnerPadding, boxDiffWidth ());
-
- requisition->width += leftInnerPadding + boxDiffWidth ();
- requisition->ascent += boxOffsetY ();
- requisition->descent += boxRestHeight ();
-
if (mustBeWidenedToAvailWidth ()) {
DBG_OBJ_MSGF ("resize", 1,
"before considering lineBreakWidth (= %d): %d * (%d + %d)",
@@ -401,6 +401,30 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
DBG_OBJ_LEAVE ();
}
+int Textblock::calcVerticalBorder (int widgetPadding, int widgetBorder,
+ int widgetMargin, int lineBorderTotal,
+ int lineMarginTotal)
+{
+ DBG_OBJ_ENTER ("resize", 0, "calcVerticalBorder", "%d, %d, %d, %d, %d",
+ widgetPadding, widgetBorder, widgetMargin, lineBorderTotal,
+ lineMarginTotal);
+
+ int result;
+
+ if (widgetPadding == 0 && widgetBorder == 0) {
+ if (lineMarginTotal - lineBorderTotal >= widgetMargin)
+ result = lineMarginTotal;
+ else
+ result = widgetMargin + lineBorderTotal;
+ } else
+ result = lineMarginTotal + widgetPadding + widgetBorder + widgetMargin;
+
+ DBG_OBJ_MSGF ("resize", 0, "=> %d", result);
+ DBG_OBJ_LEAVE ();
+
+ return result;
+}
+
/**
* Get the extremes of a word within a textblock.
*/
@@ -524,8 +548,13 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
misc::max (allocation->ascent,
// Reconstruct the initial size; see
// Textblock::sizeRequestImpl.
- (lines->size () > 0 ? lines->getRef(0)->boxAscent : 0)
- + boxOffsetY ());
+ (lines->size () > 0 ?
+ calcVerticalBorder (getStyle()->padding.top,
+ getStyle()->borderWidth.top,
+ getStyle()->margin.top + extraSpace.top,
+ lines->getRef(0)->borderAscent,
+ lines->getRef(0)->marginAscent) :
+ boxOffsetY ()));
childBaseAllocation.descent =
allocation->ascent + allocation->descent - childBaseAllocation.ascent;
@@ -593,22 +622,18 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
/* Commented lines break the n2 and n3 test cases at
* http://www.dillo.org/test/img/ */
childAllocation.y = lineYOffsetCanvas (line)
- + (line->boxAscent - word->size.ascent)
- - word->content.widget->getStyle()->margin.top;
+ + (line->borderAscent - word->size.ascent);
DBG_OBJ_MSGF ("resize", 1,
- "childAllocation.y = %d + (%d - %d) - %d = %d",
+ "childAllocation.y = %d + (%d - %d) = %d",
lineYOffsetCanvas (line),
- line->boxAscent, word->size.ascent,
- word->content.widget->getStyle()->margin.top,
+ line->borderAscent, word->size.ascent,
childAllocation.y);
childAllocation.width = word->size.width;
- childAllocation.ascent = word->size.ascent
- + word->content.widget->getStyle()->margin.top;
- childAllocation.descent = word->size.descent
- + word->content.widget->getStyle()->margin.bottom;
-
+ childAllocation.ascent = word->size.ascent;
+ childAllocation.descent = word->size.descent;
+
oldChildAllocation = word->content.widget->getAllocation();
if (childAllocation.x != oldChildAllocation->x ||
@@ -972,8 +997,8 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
} else {
Line *lastLine = lines->getRef (lines->size () - 1);
int yFirst = lineYOffsetCanvasI (0);
- int yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
- lastLine->boxDescent;
+ int yLast = lineYOffsetCanvas (lastLine) + lastLine->borderAscent +
+ lastLine->borderDescent;
if (event->yCanvas < yFirst) {
// Above the first line: take the first word.
wordIndex = 0;
@@ -986,8 +1011,8 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
lines->getRef (findLineIndexWhenAllocated (event->yWidget));
// Pointer within the break space?
- if (event->yWidget >
- (lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) {
+ if (event->yWidget > (lineYOffsetWidget (line) +
+ line->borderAscent + line->borderDescent)) {
// Choose this break.
wordIndex = line->lastWord;
charPos = core::SelectionState::END_OF_WORD;
@@ -1008,7 +1033,8 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
if (event->xWidget >= wordStartX &&
event->xWidget < nextWordStartX) {
// We have found the word.
- int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
+ int yWidgetBase =
+ lineYOffsetWidget (line) + line->borderAscent;
if (event->xWidget >= nextWordStartX - word->effSpace) {
charPos = core::SelectionState::END_OF_WORD;
@@ -1114,26 +1140,6 @@ core::Iterator *Textblock::iterator (core::Content::Type mask, bool atEnd)
return new TextblockIterator (this, mask, atEnd);
}
-/**
- * Calculate the size of a widget within the page.
- */
-void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
-{
- DBG_OBJ_ENTER ("resize", 0, "calcWidgetSize", "%p, ...", widget);
-
- widget->sizeRequest (size);
-
- // Ascent and descent in words do not contain margins.
- // TODO: Re-evaluate (GROWS)!
- core::style::Style *wstyle = widget->getStyle();
- size->ascent -= wstyle->margin.top;
- size->descent -= wstyle->margin.bottom;
-
- DBG_OBJ_MSGF ("resize", 1, "result: %d * (%d + %d)",
- size->width, size->ascent, size->descent);
- DBG_OBJ_LEAVE ();
-}
-
/*
* Draw the decorations on a word.
*/
@@ -1247,8 +1253,8 @@ void Textblock::drawWord (Line *line, int wordIndex1, int wordIndex2,
for (int i = wordIndex1; i <= wordIndex2; i++)
w += words->getRef(i)->size.width;
w += words->getRef(wordIndex2)->hyphenWidth;
- drawBox (view, style, area, xWidget, yWidgetBase - line->boxAscent,
- w, line->boxAscent + line->boxDescent, false);
+ drawBox (view, style, area, xWidget, yWidgetBase - line->borderAscent,
+ w, line->borderAscent + line->borderDescent, false);
}
if (wordIndex1 == wordIndex2 && !drawHyphen) {
@@ -1447,7 +1453,7 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
area->x, area->y, area->width, area->height);
int xWidget = line->textOffset;
- int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
+ int yWidgetBase = lineYOffsetWidget (line) + line->borderAscent;
DBG_OBJ_MSGF ("draw", 1, "line from %d to %d (%d words), at (%d, %d)",
line->firstWord, line->lastWord, words->size (),
@@ -1498,8 +1504,8 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
if (word->spaceStyle->hasBackground ())
drawBox (view, word->spaceStyle, area,
xWidget + wordSize,
- yWidgetBase - line->boxAscent, word->effSpace,
- line->boxAscent + line->boxDescent, false);
+ yWidgetBase - line->borderAscent, word->effSpace,
+ line->borderAscent + line->borderDescent, false);
drawSpace(wordIndex, view, area, xWidget + wordSize,
yWidgetBase);
}
@@ -1527,7 +1533,13 @@ int Textblock::findLineIndexWhenNotAllocated (int y)
if (lines->size() == 0)
return -1;
else
- return findLineIndex (y, lines->getRef(0)->boxAscent + boxOffsetY());
+ return
+ findLineIndex (y, calcVerticalBorder (getStyle()->padding.top,
+ getStyle()->borderWidth.top,
+ getStyle()->margin.top
+ + extraSpace.top,
+ lines->getRef(0)->borderAscent,
+ lines->getRef(0)->marginAscent));
}
int Textblock::findLineIndexWhenAllocated (int y)
@@ -1640,8 +1652,8 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace)
if ((lineIndex = findLineIndexWhenAllocated (y)) >= lines->size ())
return NULL;
line = lines->getRef (lineIndex);
- yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
- if (yWidgetBase + line->boxDescent <= y)
+ yWidgetBase = lineYOffsetWidget (line) + line->borderAscent;
+ if (yWidgetBase + line->borderDescent <= y)
return NULL;
xCursor = line->textOffset;
@@ -2304,7 +2316,7 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
}
core::Requisition size;
- calcWidgetSize (widget, &size);
+ widget->sizeRequest (&size);
Word *word = addWord (size.width, size.ascent, size.descent, 0, style);
word->content.type = core::Content::WIDGET_IN_FLOW;
word->content.widget = widget;
@@ -2581,7 +2593,7 @@ void Textblock::addParbreak (int space, core::style::Style *style)
misc::max (word->content.breakSpace, space);
lastLine->breakSpace =
misc::max (word->content.breakSpace,
- lastLine->marginDescent - lastLine->boxDescent,
+ lastLine->marginDescent - lastLine->borderDescent,
lastLine->breakSpace);
return;
}
@@ -2810,7 +2822,7 @@ void Textblock::changeLinkColor (int link, int newColor)
}
if (changed)
queueDrawArea (0, lineYOffsetWidget(line), allocation.width,
- line->boxAscent + line->boxDescent);
+ line->borderAscent + line->borderDescent);
}
}
@@ -2837,9 +2849,9 @@ void Textblock::queueDrawRange (int index1, int index2)
if (line1idx >= 0 && line2idx >= 0) {
Line *line1 = lines->getRef (line1idx),
*line2 = lines->getRef (line2idx);
- int y = lineYOffsetWidget (line1) + line1->boxAscent -
+ int y = lineYOffsetWidget (line1) + line1->borderAscent -
line1->contentAscent;
- int h = lineYOffsetWidget (line2) + line2->boxAscent +
+ int h = lineYOffsetWidget (line2) + line2->borderAscent +
line2->contentDescent - y;
queueDrawArea (0, y, allocation.width, h);
@@ -3082,71 +3094,41 @@ Textblock *Textblock::getTextblockForLine (int firstWord, int lastWord)
/**
* Includes margin, border, and padding.
*/
-int Textblock::yOffsetOfPossiblyMissingLine (int lineNo)
+int Textblock::yOffsetOfLineToBeCreated ()
{
- DBG_OBJ_ENTER ("line.yoffset", 0, "yOffsetOfPossiblyMissingLine",
- "%d <i>of %d</i>", lineNo, lines->size());
-
- int result;
-
- if (lineNo == 0) {
- result = boxOffsetY();
- DBG_OBJ_MSGF ("line.yoffset", 1, "first line: %d", result);
- } else {
- Line *prevLine = lines->getRef (lineNo - 1);
- result = boxOffsetY() + prevLine->top + prevLine->boxAscent +
- prevLine->boxDescent + prevLine->breakSpace;
- DBG_OBJ_MSGF ("line.yoffset", 1,
- "other line: %d + %d + (%d + %d) + %d = %d",
- boxOffsetY(), prevLine->top, prevLine->boxAscent,
- prevLine->boxDescent, prevLine->breakSpace, result);
- }
+ // This method does not return an exact result: the position of the
+ // new line, which does not yet exist, cannot be calculated, since
+ // the top margin of the new line (which collapses either with the
+ // top margin of the textblock widget, or the bottom margin of the
+ // last line) must be taken into account. However, this method is
+ // only called for positioning floats; here, a slight incorrectness
+ // does not cause real harm.
- DBG_OBJ_LEAVE ();
+ // (Similar applies to the line *height*, which calculated in an
+ // iterative way; see wrapWordInFlow. Using the same approach for
+ // the *position* is possible, but not worth the increased
+ // complexity.)
- return result;
-}
-
-int Textblock::heightOfPossiblyMissingLine (int lineNo)
-{
- DBG_OBJ_ENTER ("line.height", 0, "heightOfPossiblyMissingLine",
- "%d <i>of %d</i>", lineNo, lines->size());
+ DBG_OBJ_ENTER0 ("line.yoffset", 0, "yOffsetOfLineToBeCreated");
int result;
- if (lineNo < lines->size()) {
- // An existing line.
-
- Line *line = lines->getRef (lineNo);
-
- // This is sometimes called within addLine, so that the
- // condition above is true, but line->boxAscent and
- // line->boxDescent are not set appropriately. We have to
- // accumulate the heights then.
-
- if (line->finished) {
- DBG_OBJ_MSGF ("line.height", 1,
- "exists and is finished; height = %d + %d = %d",
- line->boxAscent, line->boxDescent,
- line->boxAscent + line->boxDescent);
- result = line->boxAscent + line->boxDescent;
- } else {
- DBG_OBJ_MSG ("line.height", 1, "exist but is not finished");
- result = misc::max (1, newLineAscent + newLineDescent);
- }
- } else if (lineNo == lines->size()) {
- // The line to be constructed: some words exist, but not the
- // line. Accumulate the word heights.
-
- // Old comment: Furthermore, this is in some cases incomplete:
- // see doc/dw-out-of-flow.doc. -- Still the case?
-
- DBG_OBJ_MSG ("line.height", 1, "does not exist");
- result = misc::max (1, newLineAscent + newLineDescent);
- } else
- result = 1;
+ if (lines->size () == 0) {
+ result = calcVerticalBorder (getStyle()->padding.top,
+ getStyle()->borderWidth.top + extraSpace.top,
+ getStyle()->margin.top, 0, 0);
+ DBG_OBJ_MSGF ("line.yoffset", 1, "first line: ... = %d", result);
+ } else {
+ Line *firstLine = lines->getRef (0), *lastLine = lines->getLastRef ();
+ result = calcVerticalBorder (getStyle()->padding.top,
+ getStyle()->borderWidth.top,
+ getStyle()->margin.top + extraSpace.top,
+ firstLine->borderAscent,
+ firstLine->marginAscent)
+ - firstLine->borderAscent + lastLine->top + lastLine->totalHeight (0);
+ DBG_OBJ_MSGF ("line.yoffset", 1, "other line: ... = %d", result);
+ }
- DBG_OBJ_MSGF ("line.height", 0, "result = %d", result);
DBG_OBJ_LEAVE ();
return result;
diff --git a/dw/textblock.hh b/dw/textblock.hh
index 19140492..74ef6525 100644
--- a/dw/textblock.hh
+++ b/dw/textblock.hh
@@ -37,6 +37,11 @@ namespace dw {
*
* <h3>Collapsing Spaces</h3>
*
+ * <div style="border: 2px solid #ffff00; margin-top: 0.5em;
+ * margin-bottom: 0.5em; padding: 0.5em 1em; background-color:
+ * #ffffe0"><b>Info:</b> Collapsing spaces are deprecated, in favor of
+ * collapsing margins (see below).</div>
+ *
* The idea behind this is that every paragraph has a specific vertical
* space around and that they are combined to one space, according to
* rules stated below. A paragraph consists either of the lines between
@@ -87,10 +92,11 @@ namespace dw {
* <h3>Collapsing Margins</h3>
*
* Collapsing margins, as defined in the CSS2 specification, are,
- * supported in addition to collapsing spaces. Also, spaces and margins
- * collapse themselves. I.e., the space between two paragraphs is the
- * maximum of the space calculated as described in "Collapsing Spaces"
- * and the space calculated according to the rules for collapsing margins.
+ * supported in addition to collapsing spaces. Also, spaces and
+ * margins collapse themselves. I.&nbsp;e., the space between two
+ * paragraphs is the maximum of the space calculated as described in
+ * "Collapsing Spaces" and the space calculated according to the rules
+ * for collapsing margins.
*
* (This is an intermediate hybrid state, collapsing spaces are used in
* the current version of dillo, while I implemented collapsing margins
@@ -98,6 +104,44 @@ namespace dw {
* a pure CSS-based dillo, collapsing spaces will not be needed anymore, and
* may be removed for simplicity.)
*
+ * Currently implemented cases:
+ *
+ * - The top margin of of the textblock widget and the top margin of
+ * the first line box (based on widgets in the first line) collapse.
+ *
+ * - The bottom margin of of the textblock widget and the bottom
+ * margin of the last line box collapse.
+ *
+ * - The bottom margin of a line box and the top margin of the
+ * following line collapse. Here, the break space is regarded, too.
+ *
+ * Open issues:
+ *
+ * - Only the value of Style::margin is regarded, not the result of
+ * the collapsing itself. For the widgets A, B (child of A), and C
+ * (child of B), the effective margin of A is the maximum of the
+ * *style* margins of A and B, while the effective margin of B (the
+ * collapsed margin of B and C) is ignored here. This could be
+ * solved by introducing an additional "effective" ("calculated",
+ * "collapsed") margin as an attribute of Widget.
+ *
+ * - For similar reasons, backgrounds to not work exactly. Usage of
+ * Widget::extraSpace should fix this, but it is only fully working
+ * in the GROWS branch (<http://flpsed.org/hgweb/dillo_grows>).
+ *
+ * - Do margins of inline blocks and tables collapse? Check CSS
+ * spec. (They do currently; if not, ignoring them is simple.)
+ *
+ * - Lines which only contain a BREAK should be skipped for collapsing
+ * margins, or at least all three should collapse: the previous
+ * margin, the break, and the following margin. (Compare this with
+ * the CSS spec.)
+ *
+ * - Related to this: adding breaks should be revised.
+ * Textblock::addLinebreak and Textblock::addParbreak work quite
+ * differently, and Textblock::addParbreak seems much to complex for
+ * our needs, even when spaces of lines are kept.
+ *
*
* <h3>Some Internals</h3>
*
@@ -326,20 +370,36 @@ protected:
int top; /* "top" is always relative to the top
of the first line, i.e.
page->lines[0].top is always 0. */
- int boxAscent; /* Maximum of all ascents of the words
- in this line. This is the actual
- ascent of the line. */
- int boxDescent; /* Maximum of all decents of the words
- in this line. This is the actual
- descent of the line. */
- int contentAscent; /* ??? */
- int contentDescent; /* ??? */
+ int marginAscent; /* Maximum of all total ascents
+ (including margin: hence the name)
+ of the words in this line. */
+ int marginDescent; /* Maximum of all total decents
+ (including margin: hence the name)
+ of the words in this line. */
+ int borderAscent; /* Maximum of all ascents minus margin
+ (but including padding and border:
+ hence the name) of the words in
+ this line. */
+ int borderDescent; /* Maximum of all descents minus margin
+ (but including padding and border:
+ hence the name) of the words in
+ this line. */
+ int contentAscent; /* ??? (depricated?) */
+ int contentDescent; /* ??? (depricated?) */
int breakSpace; /* Space between this line and the next one. */
- int textOffset; /* ??? */
+ int textOffset; /* ??? (to be documented) */
- /* This is similar to descent, but includes the bottom margins of the
- * widgets within this line. */
- int marginDescent;
+ /**
+ * \brief Returns the difference between two vertical lines
+ * positions: height of this line plus space below this
+ * line. The margin of the next line (marginAscent -
+ * borderAscent) must be passed seperately.
+ */
+ inline int totalHeight (int marginNextLine)
+ { return borderAscent + borderDescent
+ // Collapsing of the margins of adjacent lines is done here:
+ + lout::misc::max (marginDescent - borderDescent, marginNextLine,
+ breakSpace); }
/* Maximum of all line widths, including this line. Does not
* include the last space, but the last hyphen width. Please
@@ -348,11 +408,6 @@ protected:
* last line, not this line.*/
int maxLineWidth;
- /* Set to false at the beginning of addLine(), and to true at
- * the end. Should be checked by some methods which are called
- * by addLine(). */
- bool finished;
-
/* The word index of the last OOF reference (most importantly:
* float) whic is positioned before this line, or -1, if there
* is no OOF reference positioned before.
@@ -558,11 +613,13 @@ protected:
int hoverLink; /* The link under the mouse pointer */
void queueDrawRange (int index1, int index2);
+ int calcVerticalBorder (int widgetPadding, int widgetBorder,
+ int widgetMargin, int lineBorderTotal,
+ int lineMarginTotal);
void getWordExtremes (Word *word, core::Extremes *extremes);
void justifyLine (Line *line, int diff);
Line *addLine (int firstWord, int lastWord, int newLastOofPos,
bool temporary, int minHeight);
- void calcWidgetSize (core::Widget *widget, core::Requisition *size);
void rewrap ();
void fillParagraphs ();
void initNewLine ();
@@ -633,7 +690,7 @@ protected:
inline int _lineYOffsetWidgetAllocation (Line *line,
core::Allocation *allocation)
{
- return line->top + (allocation->ascent - lines->getRef(0)->boxAscent);
+ return line->top + (allocation->ascent - lines->getRef(0)->borderAscent);
}
inline int lineYOffsetWidget (Line *line)
@@ -646,7 +703,7 @@ protected:
* outside of lineYOffsetCanvas.
*/
inline int _lineYOffsetCanvasAllocation (Line *line,
- core::Allocation *allocation)
+ core::Allocation *allocation)
{
return allocation->y + _lineYOffsetWidgetAllocation (line, allocation);
}
@@ -656,7 +713,7 @@ protected:
*/
inline int lineYOffsetCanvas (Line *line)
{
- return _lineYOffsetCanvasAllocation(line, &childBaseAllocation);
+ return _lineYOffsetCanvasAllocation (line, &childBaseAllocation);
}
inline int lineYOffsetWidgetI (int lineIndex)
@@ -697,8 +754,7 @@ protected:
Textblock *getTextblockForLine (int firstWord, int lastWord);
void printBorderChangedErrorAndAbort (int y, Widget *vloat,
int wrapLineIndex);
- int yOffsetOfPossiblyMissingLine (int lineNo);
- int heightOfPossiblyMissingLine (int lineNo);
+ int yOffsetOfLineToBeCreated ();
bool sendSelectionEvent (core::SelectionState::EventType eventType,
core::MousePositionEvent *event);
diff --git a/dw/textblock_iterator.cc b/dw/textblock_iterator.cc
index a0eb1bf4..8da692d6 100644
--- a/dw/textblock_iterator.cc
+++ b/dw/textblock_iterator.cc
@@ -208,7 +208,7 @@ void Textblock::TextblockIterator::getAllocation (int start, int end,
&& word->content.text[start]
== 0);
}
- allocation->y = textblock->lineYOffsetCanvas (line) + line->boxAscent -
+ allocation->y = textblock->lineYOffsetCanvas (line) + line->borderAscent -
word->size.ascent;
allocation->width = word->size.width;
diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc
index 77cf46be..f9ec1ecd 100644
--- a/dw/textblock_linebreaking.cc
+++ b/dw/textblock_linebreaking.cc
@@ -400,11 +400,11 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "firstWord", line->firstWord);
DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "lastWord", line->lastWord);
- line->boxAscent = line->contentAscent = 0;
- line->boxDescent = line->contentDescent = 0;
+ line->borderAscent = line->contentAscent = 0;
+ line->borderDescent = line->contentDescent = 0;
+ line->marginAscent = 0;
line->marginDescent = 0;
line->breakSpace = 0;
- line->finished = false;
bool regardBorder = mustBorderBeRegarded (line);
line->leftOffset = misc::max (regardBorder ? newLineLeftBorder : 0,
@@ -430,13 +430,10 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
if (lines->size () == 1) {
// first line
- line->top = 0;
line->maxLineWidth = lineWidth;
line->lastOofRefPositionedBeforeThisLine = -1;
} else {
Line *prevLine = lines->getRef (lines->size () - 2);
- line->top = prevLine->top + prevLine->boxAscent +
- prevLine->boxDescent + prevLine->breakSpace;
line->maxLineWidth = misc::max (lineWidth, prevLine->maxLineWidth);
line->lastOofRefPositionedBeforeThisLine =
prevLine->lastOofRefPositionedBeforeThisLine;
@@ -449,14 +446,31 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
for(int i = line->firstWord; i <= line->lastWord; i++)
accumulateWordForLine (lineIndex, i);
+ if (lines->size () == 1)
+ line->top = 0;
+ else {
+ // See comment in Line::totalHeight for collapsing of the
+ // margins of adjacent lines.
+ Line *prevLine = lines->getRef (lines->size () - 2);
+ line->top = prevLine->top
+ + prevLine->totalHeight (line->marginAscent - line->borderAscent);
+ }
+
// Especially empty lines (possible when there are floats) have
// zero height, which may cause endless loops. For this reasons,
// the height should be positive (assuming the caller passed
// minHeight > 0).
- line->boxAscent = misc::max (line->boxAscent, minHeight);
-
- DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "boxAscent", line->boxAscent);
- DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "boxDescent", line->boxDescent);
+ line->borderAscent = misc::max (line->borderAscent, minHeight);
+ line->marginAscent = misc::max (line->marginAscent, minHeight);
+
+ DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "borderAscent",
+ line->borderAscent);
+ DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "borderDescent",
+ line->borderDescent);
+ DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "marginAscent",
+ line->marginAscent);
+ DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "marginDescent",
+ line->marginDescent);
DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "contentAscent",
line->contentAscent);
DBG_OBJ_ARRATTRSET_NUM ("lines", lineIndex, "contentDescent",
@@ -481,7 +495,6 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord,
xWidget += word->size.width + word->effSpace;
}
- line->finished = true;
line->lastOofRefPositionedBeforeThisLine =
misc::max (line->lastOofRefPositionedBeforeThisLine, newLastOofPos);
DBG_OBJ_SET_NUM ("lastLine.lastOofRefPositionedBeforeThisLine",
@@ -715,7 +728,7 @@ int Textblock::wrapWordInFlow (int wordIndex, bool wrapAll)
&breakPos);
bool floatHandled;
- int yNewLine = yOffsetOfPossiblyMissingLine (lines->size ());
+ int yNewLine = yOffsetOfLineToBeCreated ();
do {
DBG_OBJ_MSG ("construct.word", 1, "<i>floatHandled loop cycle</i>");
@@ -847,7 +860,7 @@ int Textblock::wrapWordOofRef (int wordIndex, bool wrapAll)
Word *word = words->getRef (wordIndex);
Widget *widget = word->content.widget;
- int yNewLine = yOffsetOfPossiblyMissingLine (lines->size ());
+ int yNewLine = yOffsetOfLineToBeCreated ();
// Floats, which affect either border, are handled in wrapWordInFlow; this
// is rather for positioned elements.
@@ -1487,19 +1500,13 @@ void Textblock::moveWordIndices (int wordIndex, int num, int *addIndex1)
void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
{
+ DBG_OBJ_ENTER ("construct.line", 1, "accumulateWordForLine", "%d, %d",
+ lineIndex, wordIndex);
+ DBG_MSG_WORD ("construct.line", 2, "<i>word:</i> ", wordIndex, "");
+
Line *line = lines->getRef (lineIndex);
Word *word = words->getRef (wordIndex);
- PRINTF ("[%p] ACCUMULATE_WORD_FOR_LINE (%d, %d): %d + %d / %d + %d\n",
- this, lineIndex, wordIndex, line->boxAscent, line->boxDescent,
- word->size.ascent, word->size.descent);
- //printf (" ");
- //printWord (word);
- //printf ("\n");
-
- line->boxAscent = misc::max (line->boxAscent, word->size.ascent);
- line->boxDescent = misc::max (line->boxDescent, word->size.descent);
-
int len = word->style->font->ascent;
if (word->style->valign == core::style::VALIGN_SUPER)
len += len / 2;
@@ -1510,41 +1517,41 @@ void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
len += word->style->font->ascent / 3;
line->contentDescent = misc::max (line->contentDescent, len);
- if (word->content.type == core::Content::WIDGET_IN_FLOW) {
- int collapseMarginTop = 0;
-
- line->marginDescent =
- misc::max (line->marginDescent,
- word->size.descent +
- word->content.widget->getStyle()->margin.bottom);
-
- if (lines->size () == 1 &&
- word->content.widget->isBlockLevel () &&
- getStyle ()->borderWidth.top == 0 &&
- getStyle ()->padding.top == 0) {
- // collapse top margins of parent element and its first child
- // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
- collapseMarginTop = getStyle ()->margin.top;
- }
+ int borderAscent, borderDescent, marginAscent, marginDescent;
- line->boxAscent =
- misc::max (line->boxAscent,
- word->size.ascent,
- word->size.ascent
- + word->content.widget->getStyle()->margin.top
- - collapseMarginTop);
+ DBG_OBJ_MSGF ("construct.line", 2, "size.ascent = %d, size.descent = %d",
+ word->size.ascent, word->size.descent);
+
+ if (word->content.type == core::Content::WIDGET_IN_FLOW) {
+ // TODO Consider extraSpace?
+ marginAscent = word->size.ascent;
+ marginDescent = word->size.descent;
+ borderAscent =
+ marginAscent - word->content.widget->getStyle()->margin.top;
+ borderDescent =
+ marginDescent - word->content.widget->getStyle()->margin.bottom;
word->content.widget->parentRef = makeParentRefInFlow (lineIndex);
} else {
- line->marginDescent =
- misc::max (line->marginDescent, line->boxDescent);
+ borderAscent = marginAscent = word->size.ascent;
+ borderDescent = marginDescent = word->size.descent;
if (word->content.type == core::Content::BREAK)
line->breakSpace =
- misc::max (word->content.breakSpace,
- line->marginDescent - line->boxDescent,
- line->breakSpace);
+ misc::max (word->content.breakSpace, line->breakSpace);
}
+
+ DBG_OBJ_MSGF ("construct.line", 2,
+ "borderAscent = %d, borderDescent = %d, marginAscent = %d, "
+ "marginDescent = %d",
+ borderAscent, borderDescent, marginAscent, marginDescent);
+
+ line->borderAscent = misc::max (line->borderAscent, borderAscent);
+ line->borderDescent = misc::max (line->borderDescent, borderDescent);
+ line->marginAscent = misc::max (line->marginAscent, marginAscent);
+ line->marginDescent = misc::max (line->marginDescent, marginDescent);
+
+ DBG_OBJ_LEAVE ();
}
void Textblock::accumulateWordData (int wordIndex)
@@ -1850,7 +1857,7 @@ void Textblock::rewrap ()
Word *word = words->getRef (i);
if (word->content.type == core::Content::WIDGET_IN_FLOW)
- calcWidgetSize (word->content.widget, &word->size);
+ word->content.widget->sizeRequest (&word->size);
wordWrap (i, false);
@@ -1965,7 +1972,7 @@ void Textblock::calcBorders (int lastOofRef, int height)
int firstWordOfLine =
lines->size() > 0 ? lines->getLastRef()->lastWord + 1 : 0;
int effOofRef = misc::max (lastOofRef, firstWordOfLine - 1);
- int y = yOffsetOfPossiblyMissingLine (lines->size ());
+ int y = yOffsetOfLineToBeCreated ();
for (int i = 0; i < NUM_OOFM; i++) {
oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr(i);