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();
}
예제 #3
0
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();
    }
}