예제 #1
0
static VisiblePosition logicalEndPositionForLine(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.deprecatedEditingOffset())
            return c;
        return VisiblePosition();
    }
    
    InlineBox* logicalEndBox;
    Node* logicalEndNode;
    getLogicalEndBoxAndNode(rootBox, logicalEndBox, logicalEndNode);
    if (!logicalEndNode)
        return VisiblePosition();
    
    int endOffset = 1;
    if (logicalEndNode->hasTagName(brTag))
        endOffset = 0;
    else if (logicalEndBox->isInlineTextBox()) {
        InlineTextBox* endTextBox = static_cast<InlineTextBox*>(logicalEndBox);
        endOffset = endTextBox->start();
        if (!endTextBox->isLineBreak())
            endOffset += endTextBox->len();
    }
    
    return VisiblePosition(logicalEndNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);
}
예제 #2
0
bool RootInlineBox::isHyphenated() const
{
    for (InlineBox* box = firstLeafChild(); box; box = box->nextLeafChild()) {
        if (box->isInlineTextBox()) {
            if (toInlineTextBox(box)->hasHyphen())
                return true;
        }
    }

    return false;
}
PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::previousOnLine() const
{
    ASSERT(!m_inlineTextBox || !m_inlineTextBox->layoutObject().needsLayout());
    if (!m_inlineTextBox)
        return nullptr;

    InlineBox* previous = m_inlineTextBox->prevOnLine();
    if (previous && previous->isInlineTextBox())
        return getOrCreate(&toInlineTextBox(previous)->layoutObject(), toInlineTextBox(previous));

    return nullptr;
}
PassRefPtr<AbstractInlineTextBox> AbstractInlineTextBox::nextOnLine() const
{
    ASSERT(!m_inlineTextBox || !m_inlineTextBox->layoutObject().needsLayout());
    if (!m_inlineTextBox)
        return nullptr;

    InlineBox* next = m_inlineTextBox->nextOnLine();
    if (next && next->isInlineTextBox())
        return getOrCreate(&toInlineTextBox(next)->layoutObject(), toInlineTextBox(next));

    return nullptr;
}
예제 #5
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.deprecatedEditingOffset() == 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->renderer();
        if (!endRenderer)
            return VisiblePosition();

        endNode = endRenderer->node();
        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->start();
        if (!endTextBox->isLineBreak())
            endOffset += endTextBox->len();
    }
    
    return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);
}
예제 #6
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.deprecatedEditingOffset() == 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->renderer();
        if (!startRenderer)
            return VisiblePosition();

        startNode = startRenderer->node();
        if (startNode)
            break;
        
        startBox = startBox->nextLeafChild();
    }
    
    int startOffset = 0;
    if (startBox->isInlineTextBox()) {
        InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);
        startOffset = startTextBox->start();
    }
  
    VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM);
    return positionAvoidingFirstPositionInTable(visPos);
}
예제 #7
0
void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
                                         int& topPosition, int& bottomPosition)
{
    if (isRootInlineBox()) {
        setYPos(y + maxAscent - baseline());// Place our root box.
        // CSS2: 10.8.1 - line-height on the block level element specifies the *minimum*
        // height of the generated line box
        if (hasTextChildren() && maxHeight < object()->lineHeight(m_firstLine))
            maxHeight = object()->lineHeight(m_firstLine);
    }

    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
        if (curr->object()->isPositioned())
            continue; // Positioned placeholders don't affect calculations.

        // Adjust boxes to use their real box y/height and not the logical height (as dictated by
        // line-height).
        if (curr->isInlineFlowBox())
            static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode,
                                                                    topPosition, bottomPosition);

        bool childAffectsTopBottomPos = true;

        if (curr->yPos() == PositionTop)
            curr->setYPos(y);
        else if (curr->yPos() == PositionBottom)
            curr->setYPos(y + maxHeight - curr->height());
        else {
            if (!strictMode && !curr->hasTextDescendant())
                childAffectsTopBottomPos = false;
            curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
        }
        int newY = curr->yPos();
        int newHeight = curr->height();
        int newBaseline = curr->baseline();
        int overflowTop = 0;
        int overflowBottom = 0;
        if (curr->isInlineTextBox() || curr->isInlineFlowBox()) {
            const QFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );
#ifdef APPLE_CHANGES
            newBaseline = fm.ascent();
            newY += curr->baseline() - newBaseline;
            newHeight = newBaseline+fm.descent();
#else
            // only adjust if the leading delta is superior to the font's natural leading
            if ( kAbs(fm.ascent() - curr->baseline()) > fm.leading()/2 ) {
                int ascent = fm.ascent()+fm.leading()/2;
                newBaseline = ascent;
                newY += curr->baseline() - newBaseline;
                newHeight = fm.lineSpacing();
            }
#endif
            for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) {
                overflowTop = kMin(overflowTop, shadow->y - shadow->blur);
                overflowBottom = kMax(overflowBottom, shadow->y + shadow->blur);
            }
            if (curr->isInlineFlowBox()) {
                newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
                            curr->object()->borderBottom() + curr->object()->paddingBottom();
                newY -= curr->object()->borderTop() + curr->object()->paddingTop();
                newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
            }
        } else {
            newY += curr->object()->marginTop();
            newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
            overflowTop = curr->object()->overflowTop();
            overflowBottom = curr->object()->overflowHeight() - newHeight;
       }
        curr->setYPos(newY);
        curr->setHeight(newHeight);
        curr->setBaseline(newBaseline);

        if (childAffectsTopBottomPos) {
            topPosition = kMin(topPosition, newY + overflowTop);
            bottomPosition = kMax(bottomPosition, newY + newHeight + overflowBottom);
        }
    }

    if (isRootInlineBox()) {
        const QFontMetrics &fm = object()->fontMetrics( m_firstLine );
#ifdef APPLE_CHANGES
        setHeight(fm.ascent()+fm.descent());
        setYPos(yPos() + baseline() - fm.ascent());
        setBaseline(fm.ascent());
#else
        if ( kAbs(fm.ascent() - baseline()) > fm.leading()/2 ) {
            int ascent = fm.ascent()+fm.leading()/2;
            setHeight(fm.lineSpacing());
            setYPos(yPos() + baseline() - ascent);
            setBaseline(ascent);
        }
#endif
        if (hasTextDescendant() || strictMode) {
            if (yPos() < topPosition)
                topPosition = yPos();
            if (yPos() + height() > bottomPosition)
                bottomPosition = yPos() + height();
        }
    }
}