void RenderFlow::attachLineBox(InlineFlowBox* box) { if (m_lastLineBox) { m_lastLineBox->setNextLineBox(box); box->setPreviousLineBox(m_lastLineBox); } else m_firstLineBox = box; InlineFlowBox* last = box; for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) { curr->setExtracted(false); last = curr; } m_lastLineBox = last; }
void RenderFlow::detach() { if (!documentBeingDestroyed()) { if (m_firstLineBox) { // We can't wait for RenderContainer::detach to clear the selection, // because by then we will have nuked the line boxes. if (isSelectionBorder()) canvas()->clearSelection(); // If line boxes are contained inside a root, that means we're an inline. // In that case, we need to remove all the line boxes so that the parent // lines aren't pointing to deleted children. If the first line box does // not have a parent that means they are either already disconnected or // root lines that can just be destroyed without disconnecting. if (m_firstLineBox->parent()) { for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox()) box->remove(); } // If we are an anonymous block, then our line boxes might have children // that will outlast this block. In the non-anonymous block case those // children will be destroyed by the time we return from this function. if (isAnonymousBlock()) { for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) { while (InlineBox *childBox = box->firstChild()) { childBox->remove(); } } } } else if (isInline() && parent()) parent()->dirtyLinesFromChangedChild(this, false); } deleteLineBoxes(); RenderContainer::detach(); }
void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty) { // Only paint during the foreground/selection phases. if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline) return; if (!firstLineBox()) return; // We can check the first box and last box and avoid painting if we don't // intersect. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in two extremely obscure ways. // (1) If some line in the middle has a huge overflow, it might actually extend below the last line. // (2) The overflow from an inline block on a line is not reported to the line. int maxOutlineSize = maximalOutlineSize(i.phase); int yPos = firstLineBox()->root()->topOverflow() - maxOutlineSize; int h = maxOutlineSize + lastLineBox()->root()->bottomOverflow() - yPos; yPos += _ty; if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y())) return; for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { yPos = curr->root()->topOverflow() - maxOutlineSize; h = curr->root()->bottomOverflow() + maxOutlineSize - yPos; yPos += _ty; if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y())) curr->paint(i, _tx, _ty); } if (i.phase == PaintActionOutline && i.outlineObjects) { QValueList<RenderFlow *>::iterator it;; for( it = (*i.outlineObjects).begin(); it != (*i.outlineObjects).end(); ++it ) if ((*it)->isRenderInline()) static_cast<RenderInline*>(*it)->paintOutlines(i.p, _tx, _ty); i.outlineObjects->clear(); } }
void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty) { // Only paint during the foreground/selection phases. if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline) return; bool inlineFlow = isInlineFlow(); if (inlineFlow) KHTMLAssert(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer. // If we have no lines then we have no work to do. if (!firstLineBox()) return; // We can check the first box and last box and avoid painting if we don't // intersect. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in two extremely obscure ways. // (1) If some line in the middle has a huge overflow, it might actually extend below the last line. // (2) The overflow from an inline block on a line is not reported to the line. int yPos = firstLineBox()->root()->selectionTop() - maximalOutlineSize(i.phase); int h = maximalOutlineSize(i.phase) + lastLineBox()->root()->selectionTop() + lastLineBox()->root()->selectionHeight() - yPos; yPos += _ty; if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y())) return; // See if our root lines intersect with the dirty rect. If so, then we paint // them. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. bool isPrinting = (i.p->device()->devType() == QInternal::Printer); for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) { if (isPrinting) { // FIXME: This is a feeble effort to avoid splitting a line across two pages. // It is utterly inadequate, and this should not be done at paint time at all. // The whole way objects break across pages needs to be redone. RenderCanvas* c = canvas(); // Try to avoid splitting a line vertically, but only if it's less than the height // of the entire page. if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= c->printRect().height()) { if (_ty + curr->root()->bottomOverflow() > c->printRect().y() + c->printRect().height()) { if (_ty + curr->root()->topOverflow() < c->truncatedAt()) c->setBestTruncatedAt(_ty + curr->root()->topOverflow(), this); // If we were able to truncate, don't paint. if (_ty + curr->root()->topOverflow() >= c->truncatedAt()) break; } } } int top = kMin(curr->root()->topOverflow(), curr->root()->selectionTop()) - maximalOutlineSize(i.phase); int bottom = kMax(curr->root()->selectionTop() + curr->root()->selectionHeight(), curr->root()->bottomOverflow()) + maximalOutlineSize(i.phase); h = bottom - top; yPos = _ty + top; if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y())) curr->paint(i, _tx, _ty); } if (i.phase == PaintActionOutline && i.outlineObjects) { // FIXME: Will the order in which we added objects to the dictionary be preserved? Probably not. // This means the paint order of outlines will be wrong, although this is a minor issue. QPtrDictIterator<RenderFlow> objects(*i.outlineObjects); for (objects.toFirst(); objects.current(); ++objects) { #ifdef APPLE_CHANGES if (objects.current()->style()->outlineStyleIsAuto()) objects.current()->paintFocusRing(i.p, _tx, _ty); else #endif objects.current()->paintOutlines(i.p, _tx, _ty); } i.outlineObjects->clear(); } }