Пример #1
0
void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
{
    int maxPositionTop = 0;
    int maxPositionBottom = 0;
    int maxAscent = 0;
    int maxDescent = 0;

    // Figure out if we're in strict mode.
    RenderObject* curr = object();
    while (curr && !curr->element())
        curr = curr->container();
    bool strictMode = (curr && curr->element()->getDocument()->inStrictMode());

    computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);

    if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom))
        adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);

    int maxHeight = maxAscent + maxDescent;
    int topPosition = heightOfBlock;
    int bottomPosition = heightOfBlock;
    placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition);

    setOverflowPositions(topPosition, bottomPosition);

    // Shrink boxes with no text children in quirks and almost strict mode.
    if (!strictMode)
        shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);

    heightOfBlock += maxHeight;
}
Пример #2
0
static RenderObject* getParentOfFirstLineBox(RenderObject* curr, RenderObject* marker)
{
    RenderObject* firstChild = curr->firstChild();
    if (!firstChild)
        return 0;
        
    for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) {
        if (currChild == marker)
            continue;
            
        if (currChild->isInline())
            return curr;
        
        if (currChild->isFloating() || currChild->isPositioned())
            continue;
            
        if (currChild->isTable() || !currChild->isRenderBlock())
            break;
        
        if (currChild->style()->htmlHacks() && currChild->element() &&
            (currChild->element()->hasTagName(ulTag)|| currChild->element()->hasTagName(olTag)))
            break;
            
        RenderObject* lineBox = getParentOfFirstLineBox(currChild, marker);
        if (lineBox)
            return lineBox;
    }
    
    return 0;
}
Пример #3
0
RenderObject* RenderFieldset::findLegend() const
{
    for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
        if (!legend->isFloatingOrPositioned() && legend->element() &&
                legend->element()->hasTagName(legendTag))
            return legend;
    }
    return 0;
}
Пример #4
0
static bool shouldDrawDecoration(RenderObject* obj)
{
    bool shouldDraw = false;
    for (RenderObject* curr = obj->firstChild();
         curr; curr = curr->nextSibling()) {
        if (curr->isInlineFlow()) {
            shouldDraw = true;
            break;
        }
        else if (curr->isText() && !curr->isBR() && (curr->style()->preserveWS() ||
                 !curr->element() || !curr->element()->containsOnlyWhitespace())) {
            shouldDraw = true;
            break;
        }
    }
    return shouldDraw;
}
Пример #5
0
bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer)
{
    RenderObject* stop = renderer->nextInPreOrderAfterChildren();
    for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder())
        if (o->element() && o->height())
            return true;
            
    return false;
}
// This needs to be static so it can be called by canIncreaseSelectionListLevel and canDecreaseSelectionListLevel
static bool getStartEndListChildren(const Selection& selection, Node*& start, Node*& end)
{
    if (selection.isNone())
        return false;

    // start must be in a list child
    Node* startListChild = enclosingListChild(selection.start().node());
    if (!startListChild)
        return false;
        
    // end must be in a list child
    Node* endListChild = selection.isRange() ? enclosingListChild(selection.end().node()) : startListChild;
    if (!endListChild)
        return false;
    
    // For a range selection we want the following behavior:
    //      - the start and end must be within the same overall list
    //      - the start must be at or above the level of the rest of the range
    //      - if the end is anywhere in a sublist lower than start, the whole sublist gets moved
    // In terms of this function, this means:
    //      - endListChild must start out being be a sibling of startListChild, or be in a
    //         sublist of startListChild or a sibling
    //      - if endListChild is in a sublist of startListChild or a sibling, it must be adjusted
    //         to be the ancestor that is startListChild or its sibling
    while (startListChild->parentNode() != endListChild->parentNode()) {
        endListChild = endListChild->parentNode();
        if (!endListChild)
            return false;
    }
    
    // if the selection ends on a list item with a sublist, include the entire sublist
    if (endListChild->renderer()->isListItem()) {
        RenderObject* r = endListChild->renderer()->nextSibling();
        if (r && isListElement(r->element()))
            endListChild = r->element();
    }

    start = startListChild;
    end = endListChild;
    return true;
}
Пример #7
0
static VisiblePosition endPositionForLine(const VisiblePosition& c)
{
    if (c.isNull())
        return VisiblePosition();

    RootInlineBox *rootBox = rootBoxForLine(c);
    if (!rootBox) {
        // There are VisiblePositions at offset 0 in blocks without
        // RootInlineBoxes, like empty editable blocks and bordered blocks.
        Position p = c.deepEquivalent();
        if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0)
            return c;
        return VisiblePosition();
    }
    
    // Generated content (e.g. list markers and CSS :before and :after
    // pseudoelements) have no corresponding DOM element, and so cannot be
    // represented by a VisiblePosition.  Use whatever precedes instead.
    Node *endNode;
    InlineBox *endBox = rootBox->lastLeafChild();
    while (1) {
        if (!endBox)
            return VisiblePosition();

        RenderObject *endRenderer = endBox->object();
        if (!endRenderer)
            return VisiblePosition();

        endNode = endRenderer->element();
        if (endNode)
            break;
        
        endBox = endBox->prevLeafChild();
    }
    
    int endOffset = 1;
    if (endNode->hasTagName(brTag)) {
        endOffset = 0;
    } else if (endBox->isInlineTextBox()) {
        InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox);
        endOffset = endTextBox->m_start;
        if (!endTextBox->isLineBreak())
            endOffset += endTextBox->m_len;
    }
    
    return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);
}
Пример #8
0
static VisiblePosition startPositionForLine(const VisiblePosition& c)
{
    if (c.isNull())
        return VisiblePosition();

    RootInlineBox *rootBox = rootBoxForLine(c);
    if (!rootBox) {
        // There are VisiblePositions at offset 0 in blocks without
        // RootInlineBoxes, like empty editable blocks and bordered blocks.
        Position p = c.deepEquivalent();
        if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0)
            return positionAvoidingFirstPositionInTable(c);
        
        return VisiblePosition();
    }
    
    // Generated content (e.g. list markers and CSS :before and :after
    // pseudoelements) have no corresponding DOM element, and so cannot be
    // represented by a VisiblePosition.  Use whatever follows instead.
    InlineBox *startBox = rootBox->firstLeafChild();
    Node *startNode;
    while (1) {
        if (!startBox)
            return VisiblePosition();

        RenderObject *startRenderer = startBox->object();
        if (!startRenderer)
            return VisiblePosition();

        startNode = startRenderer->element();
        if (startNode)
            break;
        
        startBox = startBox->nextLeafChild();
    }
    
    int startOffset = 0;
    if (startBox->isInlineTextBox()) {
        InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);
        startOffset = startTextBox->m_start;
    }
  
    VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM);
    return positionAvoidingFirstPositionInTable(visPos);
}
Пример #9
0
AccessibilityObject* AccessibilityTableRow::headerObject()
{
    AccessibilityChildrenVector rowChildren = children();
    if (!rowChildren.size())
        return 0;
    
    // check the first element in the row to see if it is a TH element
    AccessibilityObject* cell = rowChildren[0].get();
    if (!cell->isTableCell())
        return 0;
    
    RenderObject* cellRenderer = static_cast<AccessibilityTableCell*>(cell)->renderer();
    if (!cellRenderer)
        return 0;
    
    Node* cellNode = cellRenderer->element();
    if (!cellNode || !cellNode->hasTagName(thTag))
        return 0;
    
    return cell;
}
Пример #10
0
void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer)
{
    // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
    // updateRendering.  It will then call back to us with new information.
    bool animating = false;
    RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
    for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 
         it != animationsEnd; ++it) {
        RenderObject* renderer = it->first;
        CompositeAnimation* compAnim = it->second;
        if (!compAnim->suspended() && compAnim->animating()) {
            animating = true;
            compAnim->setAnimating(false);
            
            Node* node = renderer->element();
            ASSERT(!node || (node->document() && !node->document()->inPageCache()));
            node->setChanged(AnimationStyleChange);
        }
    }
    
    m_frame->document()->updateRendering();
    
    updateAnimationTimer();
}
Пример #11
0
VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x)
{
    Position p = visiblePosition.deepEquivalent();
    Node *node = p.node();
    Node* highestRoot = highestEditableRoot(p);
    if (!node)
        return VisiblePosition();
    
    node->document()->updateLayoutIgnorePendingStylesheets();

    RenderObject *renderer = node->renderer();
    if (!renderer)
        return VisiblePosition();

    RenderBlock *containingBlock = 0;
    RootInlineBox *root = 0;
    InlineBox* box;
    int ignoredCaretOffset;
    visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
    if (box) {
        root = box->root()->nextRootBox();
        if (root)
            containingBlock = renderer->containingBlock();
    }

    if (!root) {
        // This containing editable block does not have a next line.
        // Need to move forward to next containing editable block in this root editable
        // block and find the first root line box in that block.
        Node* startBlock = enclosingBlock(node);
        Node* n = nextLeafWithSameEditability(node, p.offset());
        while (n && startBlock == enclosingBlock(n))
            n = nextLeafWithSameEditability(n);
        while (n) {
            if (highestEditableRoot(Position(n, 0)) != highestRoot)
                break;
            Position pos(n, caretMinOffset(n));
            if (pos.isCandidate()) {
                ASSERT(n->renderer());
                pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
                if (box) {
                    // next root line box found
                    root = box->root();
                    containingBlock = n->renderer()->containingBlock();
                    break;
                }

                return VisiblePosition(pos, DOWNSTREAM);
            }
            n = nextLeafWithSameEditability(n);
        }
    }
    
    if (root) {
        // FIXME: Can be wrong for multi-column layout.
        int absx, absy;
        containingBlock->absolutePositionForContent(absx, absy);
        if (containingBlock->hasOverflowClip())
            containingBlock->layer()->subtractScrollOffset(absx, absy);
        RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object();
        Node* node = renderer->element();
        if (editingIgnoresContent(node))
            return Position(node->parent(), node->nodeIndex());
        return renderer->positionForCoordinates(x - absx, root->topOverflow());
    }    

    // Could not find a next line. This means we must already be on the last line.
    // Move to the end of the content in this block, which effectively moves us
    // to the end of the line we're on.
    Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement();
    return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM);
}