2 * This file is part of the html renderer for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 1999 Antti Koivisto (koivisto@kde.org)
6 * Copyright (C) 2003 Apple Computer, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
23 // -------------------------------------------------------------------------
30 #include "rendering/render_flow.h"
31 #include "rendering/render_text.h"
32 #include "rendering/render_table.h"
33 #include "rendering/render_canvas.h"
34 #include "xml/dom_nodeimpl.h"
35 #include "xml/dom_docimpl.h"
36 #include "html/html_formimpl.h"
37 #include "render_inline.h"
38 #include "render_block.h"
39 #include "render_arena.h"
40 #include "render_line.h"
42 #include "khtmlview.h"
46 using namespace khtml;
48 RenderFlow* RenderFlow::createAnonymousFlow(DOM::DocumentImpl* doc, RenderStyle* style)
51 if (style->display() == INLINE)
52 result = new (doc->renderArena()) RenderInline(doc);
54 result = new (doc->renderArena()) RenderBlock(doc);
55 result->setStyle(style);
59 RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
61 if (beforeChild && beforeChild->parent() == this)
64 RenderFlow* curr = continuation();
65 RenderFlow* nextToLast = this;
66 RenderFlow* last = this;
68 if (beforeChild && beforeChild->parent() == curr) {
69 if (curr->firstChild() == beforeChild)
76 curr = curr->continuation();
79 if (!beforeChild && !last->firstChild())
84 void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
86 RenderFlow* flow = continuationBefore(beforeChild);
87 KHTMLAssert(!beforeChild || beforeChild->parent()->isRenderBlock() ||
88 beforeChild->parent()->isRenderInline());
89 RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) :
90 (flow->continuation() ? flow->continuation() : flow);
92 if (newChild->isFloatingOrPositioned())
93 return beforeChildParent->addChildToFlow(newChild, beforeChild);
95 // A continuation always consists of two potential candidates: an inline or an anonymous
96 // block box holding block children.
97 bool childInline = newChild->isInline();
98 bool bcpInline = beforeChildParent->isInline();
99 bool flowInline = flow->isInline();
101 if (flow == beforeChildParent)
102 return flow->addChildToFlow(newChild, beforeChild);
104 // The goal here is to match up if we can, so that we can coalesce and create the
105 // minimal # of continuations needed for the inline.
106 if (childInline == bcpInline)
107 return beforeChildParent->addChildToFlow(newChild, beforeChild);
108 else if (flowInline == childInline)
109 return flow->addChildToFlow(newChild, 0); // Just treat like an append.
111 return beforeChildParent->addChildToFlow(newChild, beforeChild);
115 void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
118 kdDebug( 6040 ) << renderName() << "(RenderFlow)::addChild( " << newChild->renderName() <<
119 ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
120 kdDebug( 6040 ) << "current height = " << m_height << endl;
124 return addChildWithContinuation(newChild, beforeChild);
125 return addChildToFlow(newChild, beforeChild);
128 void RenderFlow::extractLineBox(InlineFlowBox* box)
130 m_lastLineBox = box->prevFlowBox();
131 if (box == m_firstLineBox)
133 if (box->prevLineBox())
134 box->prevLineBox()->setNextLineBox(0);
135 box->setPreviousLineBox(0);
136 for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
137 curr->setExtracted();
140 void RenderFlow::attachLineBox(InlineFlowBox* box)
143 m_lastLineBox->setNextLineBox(box);
144 box->setPreviousLineBox(m_lastLineBox);
147 m_firstLineBox = box;
148 InlineFlowBox* last = box;
149 for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
150 curr->setExtracted(false);
153 m_lastLineBox = last;
156 void RenderFlow::removeLineBox(InlineFlowBox* box)
158 if (box == m_firstLineBox)
159 m_firstLineBox = box->nextFlowBox();
160 if (box == m_lastLineBox)
161 m_lastLineBox = box->prevFlowBox();
162 if (box->nextLineBox())
163 box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
164 if (box->prevLineBox())
165 box->prevLineBox()->setNextLineBox(box->nextLineBox());
168 void RenderFlow::deleteLineBoxes()
170 if (m_firstLineBox) {
171 RenderArena* arena = renderArena();
172 InlineRunBox *curr=m_firstLineBox, *next=0;
174 next = curr->nextLineBox();
183 void RenderFlow::detach()
185 if (!documentBeingDestroyed()) {
186 if (m_firstLineBox) {
187 // We can't wait for RenderContainer::detach to clear the selection,
188 // because by then we will have nuked the line boxes.
189 if (isSelectionBorder())
190 canvas()->clearSelection();
192 // If line boxes are contained inside a root, that means we're an inline.
193 // In that case, we need to remove all the line boxes so that the parent
194 // lines aren't pointing to deleted children. If the first line box does
195 // not have a parent that means they are either already disconnected or
196 // root lines that can just be destroyed without disconnecting.
197 if (m_firstLineBox->parent()) {
198 for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox())
202 // If we are an anonymous block, then our line boxes might have children
203 // that will outlast this block. In the non-anonymous block case those
204 // children will be destroyed by the time we return from this function.
205 if (isAnonymousBlock()) {
206 for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) {
207 while (InlineBox *childBox = box->firstChild()) {
213 else if (isInline() && parent())
214 parent()->dirtyLinesFromChangedChild(this);
219 RenderContainer::detach();
222 void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
224 if (!parent() || selfNeedsLayout() || isTable())
227 // For an empty inline, go ahead and propagate the check up to our parent.
228 if (isInline() && !firstLineBox())
229 return parent()->dirtyLinesFromChangedChild(this);
231 // Try to figure out which line box we belong in. First try to find a previous
232 // line box by examining our siblings. If we didn't find a line box, then use our
233 // parent's first line box.
234 RootInlineBox* box = 0;
235 RenderObject* curr = 0;
236 for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
237 if (curr->isFloatingOrPositioned())
240 if (curr->isReplaced()) {
241 InlineBox* wrapper = curr->inlineBoxWrapper();
243 box = wrapper->root();
245 else if (curr->isText()) {
246 InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
248 box = textBox->root();
250 else if (curr->isInlineFlow()) {
251 InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
253 box = runBox->root();
259 if (!box && firstLineBox())
260 box = firstLineBox()->root();
262 // If we found a line box, then dirty it.
264 RootInlineBox* adjacentBox;
267 // dirty the adjacent lines that might be affected
268 // NOTE: we dirty the previous line because RootInlineBox objects cache
269 // the address of the first object on the next line after a BR, which we may be
270 // invalidating here. For more info, see how RenderBlock::layoutInlineChildren
271 // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak,
272 // despite the name, actually returns the first RenderObject after the BR.
273 // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
274 adjacentBox = box->prevRootBox();
276 adjacentBox->markDirty();
277 if (child->isBR() || (curr && curr->isBR())) {
278 adjacentBox = box->nextRootBox();
280 adjacentBox->markDirty();
285 short RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
288 RenderStyle* s = style(firstLine);
289 Length lh = s->lineHeight();
292 if (m_lineHeight == -1)
293 m_lineHeight = RenderObject::lineHeight(false);
296 return s->fontMetrics().lineSpacing();
299 return lh.minWidth(s->font().pixelSize());
303 if (m_lineHeight == -1)
304 m_lineHeight = RenderObject::lineHeight(false);
308 void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
310 if (!isRootLineBox && isReplaced())
311 return RenderContainer::dirtyLineBoxes(fullLayout, isRootLineBox);
316 for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
317 curr->dirtyLineBoxes();
321 InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
323 if (!isRootLineBox &&
324 (isReplaced() || makePlaceHolderBox)) // Inline tables and inline blocks
325 return RenderContainer::createInlineBox(false, isRootLineBox); // (or positioned element placeholders).
327 InlineFlowBox* flowBox = 0;
329 flowBox = new (renderArena()) InlineFlowBox(this);
331 flowBox = new (renderArena()) RootInlineBox(this);
334 m_firstLineBox = m_lastLineBox = flowBox;
336 m_lastLineBox->setNextLineBox(flowBox);
337 flowBox->setPreviousLineBox(m_lastLineBox);
338 m_lastLineBox = flowBox;
344 void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty)
346 // Only paint during the foreground/selection phases.
347 if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline)
350 bool inlineFlow = isInlineFlow();
352 KHTMLAssert(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
354 // If we have no lines then we have no work to do.
358 // We can check the first box and last box and avoid painting if we don't
359 // intersect. This is a quick short-circuit that we can take to avoid walking any lines.
360 // FIXME: This check is flawed in two extremely obscure ways.
361 // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
362 // (2) The overflow from an inline block on a line is not reported to the line.
363 int yPos = firstLineBox()->root()->selectionTop() - maximalOutlineSize(i.phase);
364 int h = maximalOutlineSize(i.phase) + lastLineBox()->root()->selectionTop() + lastLineBox()->root()->selectionHeight() - yPos;
366 if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
369 // See if our root lines intersect with the dirty rect. If so, then we paint
370 // them. Note that boxes can easily overlap, so we can't make any assumptions
371 // based off positions of our first line box or our last line box.
372 bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
373 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
375 // FIXME: This is a feeble effort to avoid splitting a line across two pages.
376 // It is utterly inadequate, and this should not be done at paint time at all.
377 // The whole way objects break across pages needs to be redone.
378 RenderCanvas* c = canvas();
379 // Try to avoid splitting a line vertically, but only if it's less than the height
380 // of the entire page.
381 if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= c->printRect().height()) {
382 if (_ty + curr->root()->bottomOverflow() > c->printRect().y() + c->printRect().height()) {
383 if (_ty + curr->root()->topOverflow() < c->truncatedAt())
384 c->setBestTruncatedAt(_ty + curr->root()->topOverflow(), this);
385 // If we were able to truncate, don't paint.
386 if (_ty + curr->root()->topOverflow() >= c->truncatedAt())
392 int top = kMin(curr->root()->topOverflow(), curr->root()->selectionTop()) - maximalOutlineSize(i.phase);
393 int bottom = kMax(curr->root()->selectionTop() + curr->root()->selectionHeight(), curr->root()->bottomOverflow()) + maximalOutlineSize(i.phase);
396 if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
397 curr->paint(i, _tx, _ty);
400 if (i.phase == PaintActionOutline && i.outlineObjects) {
401 // FIXME: Will the order in which we added objects to the dictionary be preserved? Probably not.
402 // This means the paint order of outlines will be wrong, although this is a minor issue.
403 QPtrDictIterator<RenderFlow> objects(*i.outlineObjects);
404 for (objects.toFirst(); objects.current(); ++objects) {
406 if (objects.current()->style()->outlineStyleIsAuto())
407 objects.current()->paintFocusRing(i.p, _tx, _ty);
410 objects.current()->paintOutlines(i.p, _tx, _ty);
412 i.outlineObjects->clear();
416 bool RenderFlow::hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
418 if (hitTestAction != HitTestForeground)
421 bool inlineFlow = isInlineFlow();
423 KHTMLAssert(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
425 // If we have no lines then we have no work to do.
429 // We can check the first box and last box and avoid hit testing if we don't
430 // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
431 // FIXME: This check is flawed in two extremely obscure ways.
432 // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
433 // (2) The overflow from an inline block on a line is not reported to the line.
434 if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
437 // See if our root lines contain the point. If so, then we hit test
438 // them further. Note that boxes can easily overlap, so we can't make any assumptions
439 // based off positions of our first line box or our last line box.
440 for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
441 if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
442 bool inside = curr->nodeAtPoint(i, x, y, tx, ty);
453 QRect RenderFlow::getAbsoluteRepaintRect()
455 if (isInlineFlow()) {
456 // Find our leftmost position.
458 int top = firstLineBox() ? firstLineBox()->yPos() : 0;
459 for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
460 if (curr == firstLineBox() || curr->xPos() < left)
463 // Now invalidate a rectangle.
464 int ow = style() ? style()->outlineSize() : 0;
468 // We need to add in the relative position offsets of any inlines (including us) up to our
470 RenderBlock* cb = containingBlock();
471 for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb;
472 inlineFlow = inlineFlow->parent()) {
473 if (inlineFlow->style()->position() == RELATIVE && inlineFlow->layer())
474 inlineFlow->layer()->relativePositionOffset(left, top);
477 QRect r(-ow+left, -ow+top, width()+ow*2, height()+ow*2);
478 if (cb->hasOverflowClip()) {
479 // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
480 // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
481 // anyway if its size does change.
484 QRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
485 cb->layer()->subtractScrollOffset(x,y); // For overflow:auto/scroll/hidden.
486 QRect repaintRect(x, y, r.width(), r.height());
487 r = repaintRect.intersect(boxRect);
489 cb->computeAbsoluteRepaintRect(r);
492 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
493 if (!curr->isText()) {
494 QRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
495 r = r.unite(childRect);
499 if (continuation() && !continuation()->isInline()) {
500 QRect contRect = continuation()->getAbsoluteRepaintRectWithOutline(ow);
501 r = r.unite(contRect);
508 if (firstLineBox() && firstLineBox()->topOverflow() < 0) {
509 int ow = style() ? style()->outlineSize() : 0;
510 QRect r(-ow, -ow+firstLineBox()->topOverflow(),
511 overflowWidth(false)+ow*2,
512 overflowHeight(false)+ow*2-firstLineBox()->topOverflow());
513 computeAbsoluteRepaintRect(r);
518 return RenderContainer::getAbsoluteRepaintRect();
522 RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
524 int bottom = RenderContainer::lowestPosition(includeOverflowInterior, includeSelf);
525 if (!includeOverflowInterior && hasOverflowClip())
528 // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
529 // For now, we have to descend into all the children, since we may have a huge abs div inside
530 // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
532 for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
533 if (!c->isFloatingOrPositioned() && !c->isText()) {
534 int lp = c->yPos() + c->lowestPosition(false);
535 bottom = kMax(bottom, lp);
542 int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
544 int right = RenderContainer::rightmostPosition(includeOverflowInterior, includeSelf);
545 if (!includeOverflowInterior && hasOverflowClip())
548 // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
549 // For now, we have to descend into all the children, since we may have a huge abs div inside
550 // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
552 for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
553 if (!c->isFloatingOrPositioned() && !c->isText()) {
554 int rp = c->xPos() + c->rightmostPosition(false);
555 right = kMax(right, rp);
562 int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
564 int left = RenderContainer::leftmostPosition(includeOverflowInterior, includeSelf);
565 if (!includeOverflowInterior && hasOverflowClip())
568 // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
569 // For now, we have to descend into all the children, since we may have a huge abs div inside
570 // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
572 for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
573 if (!c->isFloatingOrPositioned() && !c->isText()) {
574 int lp = c->xPos() + c->leftmostPosition(false);
575 left = kMin(left, lp);
582 QRect RenderFlow::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
584 if (firstChild() || style()->display() == INLINE) {
585 // Do the normal calculation
586 return RenderContainer::caretRect(offset, affinity, extraWidthToEndOfLine);
589 // This is a special case:
590 // The element is not an inline element, and it's empty. So we have to
591 // calculate a fake position to indicate where objects are to be inserted.
593 int _x, _y, width, height;
595 // EDIT FIXME: this does neither take into regard :first-line nor :first-letter
596 // However, as soon as some content is entered, the line boxes will be
597 // constructed properly and this kludge is not called any more. So only
598 // the caret size of an empty :first-line'd block is wrong, but I think we
599 // can live with that.
600 RenderStyle *currentStyle = style(true);
601 //height = currentStyle->fontMetrics().height();
602 height = lineHeight(true);
605 // EDIT FIXME: This needs to account for text direction
606 int w = this->width();
607 switch (currentStyle->textAlign()) {
628 if (extraWidthToEndOfLine) {
629 if (isRenderBlock()) {
630 *extraWidthToEndOfLine = this->width() - (_x + width);
632 int myRight = _x + width;
634 absolutePosition(myRight, ignore);
636 int containerRight = containingBlock()->xPos() + containingBlockWidth();
637 absolutePosition(containerRight, ignore);
639 *extraWidthToEndOfLine = containerRight - myRight;
644 absolutePosition(absx, absy, false);
645 _x += absx + paddingLeft() + borderLeft();
646 _y += absy + paddingTop() + borderTop();
648 return QRect(_x, _y, width, height);
652 void RenderFlow::addFocusRingRects(QPainter *p, int _tx, int _ty)
654 // Only paint focus ring around outermost contenteditable element.
655 // But skip the body element if it is outermost.
656 if (element() && element()->isContentEditable()) {
657 if (element()->parentNode() && !element()->parentNode()->isContentEditable() && element()->id() != ID_BODY)
658 p->addFocusRingRect(_tx, _ty, width(), height());
662 for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
663 p->addFocusRingRect(_tx + curr->xPos(),
669 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
671 curr->addFocusRingRects(p, _tx + curr->xPos(), _ty + curr->yPos());
675 continuation()->addFocusRingRects(p,
676 _tx - containingBlock()->xPos() + continuation()->xPos(),
677 _ty - containingBlock()->yPos() + continuation()->yPos());
680 void RenderFlow::paintFocusRing(QPainter *p, int tx, int ty)
682 int ow = style()->outlineWidth();
683 QColor oc = style()->outlineColor();
685 oc = style()->color();
687 p->initFocusRing(ow, style()->outlineOffset(), oc);
688 addFocusRingRects(p, tx, ty);
694 void RenderFlow::paintOutlines(QPainter *p, int _tx, int _ty)
696 if (style()->outlineStyle() <= BHIDDEN)
699 QPtrList <QRect> rects;
700 rects.setAutoDelete(true);
702 rects.append(new QRect(0,0,0,0));
703 for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
704 rects.append(new QRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
706 rects.append(new QRect(0,0,0,0));
708 for (unsigned int i = 1; i < rects.count() - 1; i++)
709 paintOutlineForLine(p, _tx, _ty, *rects.at(i-1), *rects.at(i), *rects.at(i+1));
712 void RenderFlow::paintOutlineForLine(QPainter *p, int tx, int ty, const QRect &lastline, const QRect &thisline, const QRect &nextline)
714 int ow = style()->outlineWidth();
715 EBorderStyle os = style()->outlineStyle();
716 QColor oc = style()->outlineColor();
718 oc = style()->color();
720 int offset = style()->outlineOffset();
722 int t = ty + thisline.top() - offset;
723 int l = tx + thisline.left() - offset;
724 int b = ty + thisline.bottom() + offset + 1;
725 int r = tx + thisline.right() + offset + 1;
730 t - (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : 0),
732 b + (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : 0),
734 oc, style()->color(), os,
735 (lastline.isEmpty() || thisline.left() < lastline.left() || lastline.right() <= thisline.left() ? ow : -ow),
736 (nextline.isEmpty() || thisline.left() <= nextline.left() || nextline.right() <= thisline.left() ? ow : -ow),
742 t - (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : 0),
744 b + (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : 0),
746 oc, style()->color(), os,
747 (lastline.isEmpty() || lastline.right() < thisline.right() || thisline.right() <= lastline.left() ? ow : -ow),
748 (nextline.isEmpty() || nextline.right() <= thisline.right() || thisline.right() <= nextline.left() ? ow : -ow),
751 if ( thisline.left() < lastline.left())
755 kMin(r+ow, (lastline.isValid()? tx+lastline.left() : 1000000)),
757 BSTop, oc, style()->color(), os,
759 (lastline.isValid() && tx+lastline.left()+1<r+ow ? -ow : ow),
762 if (lastline.right() < thisline.right())
764 kMax(lastline.isValid()?tx + lastline.right() + 1:-1000000, l - ow),
768 BSTop, oc, style()->color(), os,
769 (lastline.isValid() && l-ow < tx+lastline.right()+1 ? -ow : ow),
774 if ( thisline.left() < nextline.left())
778 kMin(r+ow, nextline.isValid()? tx+nextline.left()+1 : 1000000),
780 BSBottom, oc, style()->color(), os,
782 (nextline.isValid() && tx+nextline.left()+1<r+ow? -ow : ow),
785 if (nextline.right() < thisline.right())
787 kMax(nextline.isValid()?tx+nextline.right()+1:-1000000 , l-ow),
791 BSBottom, oc, style()->color(), os,
792 (nextline.isValid() && l-ow < tx+nextline.right()+1? -ow : ow),