⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renderinline.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of the render object implementation for KHTML. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) *           (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderInline.h"#include "FloatQuad.h"#include "GraphicsContext.h"#include "HitTestResult.h"#include "Page.h"#include "RenderArena.h"#include "RenderBlock.h"#include "RenderView.h"#include "VisiblePosition.h"#if ENABLE(DASHBOARD_SUPPORT)#include "Frame.h"#endifusing namespace std;namespace WebCore {RenderInline::RenderInline(Node* node)    : RenderBoxModelObject(node)    , m_continuation(0)    , m_lineHeight(-1)    , m_verticalPosition(PositionUndefined){    setChildrenInline(true);}RenderInline::~RenderInline(){}void RenderInline::destroy(){    // Detach our continuation first.    if (m_continuation)        m_continuation->destroy();    m_continuation = 0;        // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will    // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.    children()->destroyLeftoverChildren();    if (!documentBeingDestroyed()) {        if (firstLineBox()) {            // We can't wait for RenderBoxModelObject::destroy to clear the selection,            // because by then we will have nuked the line boxes.            // FIXME: The SelectionController should be responsible for this when it            // is notified of DOM mutations.            if (isSelectionBorder())                view()->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 (firstLineBox()->parent()) {                for (InlineRunBox* box = firstLineBox(); box; box = box->nextLineBox())                    box->remove();            }        } else if (isInline() && parent())            parent()->dirtyLinesFromChangedChild(this);    }    m_lineBoxes.deleteLineBoxes(renderArena());    RenderBoxModelObject::destroy();}RenderInline* RenderInline::inlineContinuation() const{    if (!m_continuation || m_continuation->isInline())        return toRenderInline(m_continuation);    return toRenderBlock(m_continuation)->inlineContinuation();}void RenderInline::updateBoxModelInfoFromStyle(){    RenderBoxModelObject::updateBoxModelInfoFromStyle();    setInline(true); // Needed for run-ins, since run-in is considered a block display type.    // FIXME: Support transforms and reflections on inline flows someday.    setHasTransform(false);    setHasReflection(false);    }void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle){    RenderBoxModelObject::styleDidChange(diff, oldStyle);    // Ensure that all of the split inlines pick up the new style. We    // only do this if we're an inline, since we don't want to propagate    // a block's style to the other inlines.    // e.g., <font>foo <h4>goo</h4> moo</font>.  The <font> inlines before    // and after the block share the same style, but the block doesn't    // need to pass its style on to anyone else.    for (RenderInline* currCont = inlineContinuation(); currCont; currCont = currCont->inlineContinuation()) {        RenderBoxModelObject* nextCont = currCont->continuation();        currCont->setContinuation(0);        currCont->setStyle(style());        currCont->setContinuation(nextCont);    }    m_lineHeight = -1;    // Update pseudos for :before and :after now.    if (!isAnonymous() && document()->usesBeforeAfterRules()) {        children()->updateBeforeAfterContent(this, BEFORE);        children()->updateBeforeAfterContent(this, AFTER);    }}static inline bool isAfterContent(RenderObject* child){    if (!child)        return false;    if (child->style()->styleType() != AFTER)        return false;    // Text nodes don't have their own styles, so ignore the style on a text node.    if (child->isText() && !child->isBR())        return false;    return true;}void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild){    if (continuation())        return addChildToContinuation(newChild, beforeChild);    return addChildIgnoringContinuation(newChild, beforeChild);}static RenderBoxModelObject* nextContinuation(RenderObject* renderer){    if (renderer->isInline() && !renderer->isReplaced())        return toRenderInline(renderer)->continuation();    return toRenderBlock(renderer)->inlineContinuation();}RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild){    if (beforeChild && beforeChild->parent() == this)        return this;    RenderBoxModelObject* curr = nextContinuation(this);    RenderBoxModelObject* nextToLast = this;    RenderBoxModelObject* last = this;    while (curr) {        if (beforeChild && beforeChild->parent() == curr) {            if (curr->firstChild() == beforeChild)                return last;            return curr;        }        nextToLast = last;        last = curr;        curr = nextContinuation(curr);    }    if (!beforeChild && !last->firstChild())        return nextToLast;    return last;}void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild){    // Make sure we don't append things after :after-generated content if we have it.    if (!beforeChild && isAfterContent(lastChild()))        beforeChild = lastChild();    if (!newChild->isInline() && !newChild->isFloatingOrPositioned()) {        // We are placing a block inside an inline. We have to perform a split of this        // inline into continuations.  This involves creating an anonymous block box to hold        // |newChild|.  We then make that block box a continuation of this inline.  We take all of        // the children after |beforeChild| and put them in a clone of this object.        RefPtr<RenderStyle> newStyle = RenderStyle::create();        newStyle->inheritFrom(style());        newStyle->setDisplay(BLOCK);        RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);        newBox->setStyle(newStyle.release());        RenderBoxModelObject* oldContinuation = continuation();        setContinuation(newBox);        // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content        // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after        // content gets properly destroyed.        bool isLastChild = (beforeChild == lastChild());        if (document()->usesBeforeAfterRules())            children()->updateBeforeAfterContent(this, AFTER);        if (isLastChild && beforeChild != lastChild())            beforeChild = 0; // We destroyed the last child, so now we need to update our insertion                             // point to be 0.  It's just a straight append now.        splitFlow(beforeChild, newBox, newChild, oldContinuation);        return;    }    RenderBoxModelObject::addChild(newChild, beforeChild);    newChild->setNeedsLayoutAndPrefWidthsRecalc();}RenderInline* RenderInline::cloneInline(RenderInline* src){    RenderInline* o = new (src->renderArena()) RenderInline(src->node());    o->setStyle(src->style());    return o;}void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,                                RenderBlock* middleBlock,                                RenderObject* beforeChild, RenderBoxModelObject* oldCont){    // Create a clone of this inline.    RenderInline* clone = cloneInline(this);    clone->setContinuation(oldCont);    // Now take all of the children from beforeChild to the end and remove    // them from |this| and place them in the clone.    RenderObject* o = beforeChild;    while (o) {        RenderObject* tmp = o;        o = tmp->nextSibling();        clone->addChildIgnoringContinuation(children()->removeChildNode(this, tmp), 0);        tmp->setNeedsLayoutAndPrefWidthsRecalc();    }    // Hook |clone| up as the continuation of the middle block.    middleBlock->setInlineContinuation(clone);    // We have been reparented and are now under the fromBlock.  We need    // to walk up our inline parent chain until we hit the containing block.    // Once we hit the containing block we're done.    RenderBoxModelObject* curr = static_cast<RenderBoxModelObject*>(parent());    RenderBoxModelObject* currChild = this;        // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.    // There will eventually be a better approach to this problem that will let us nest to a much    // greater depth (see bugzilla bug 13430) but for now we have a limit.  This *will* result in    // incorrect rendering, but the alternative is to hang forever.    unsigned splitDepth = 1;    const unsigned cMaxSplitDepth = 200;     while (curr && curr != fromBlock) {        ASSERT(curr->isRenderInline());        if (splitDepth < cMaxSplitDepth) {            // Create a new clone.            RenderInline* cloneChild = clone;            clone = cloneInline(toRenderInline(curr));            // Insert our child clone as the first child.            clone->addChildIgnoringContinuation(cloneChild, 0);            // Hook the clone up as a continuation of |curr|.            RenderInline* inlineCurr = toRenderInline(curr);            oldCont = inlineCurr->continuation();            inlineCurr->setContinuation(clone);            clone->setContinuation(oldCont);            // Someone may have indirectly caused a <q> to split.  When this happens, the :after content            // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after            // content gets properly destroyed.            if (document()->usesBeforeAfterRules())                inlineCurr->children()->updateBeforeAfterContent(this, AFTER);            // Now we need to take all of the children starting from the first child            // *after* currChild and append them all to the clone.            o = currChild->nextSibling();            while (o) {                RenderObject* tmp = o;                o = tmp->nextSibling();                clone->addChildIgnoringContinuation(inlineCurr->children()->removeChildNode(curr, tmp), 0);                tmp->setNeedsLayoutAndPrefWidthsRecalc();            }        }                // Keep walking up the chain.        currChild = curr;        curr = static_cast<RenderBoxModelObject*>(curr->parent());        splitDepth++;    }    // Now we are at the block level. We need to put the clone into the toBlock.    toBlock->children()->appendChildNode(toBlock, clone);    // Now take all the children after currChild and remove them from the fromBlock    // and put them in the toBlock.    o = currChild->nextSibling();    while (o) {        RenderObject* tmp = o;        o = tmp->nextSibling();        toBlock->children()->appendChildNode(toBlock, fromBlock->children()->removeChildNode(fromBlock, tmp));    }}void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,                             RenderObject* newChild, RenderBoxModelObject* oldCont){    RenderBlock* pre = 0;    RenderBlock* block = containingBlock();        // Delete our line boxes before we do the inline split into continuations.    block->deleteLineBoxTree();        bool madeNewBeforeBlock = false;    if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {        // We can reuse this block and make it the preBlock of the next continuation.        pre = block;        block = block->containingBlock();    } else {        // No anonymous block available for use.  Make one.        pre = block->createAnonymousBlock();        madeNewBeforeBlock = true;    }    RenderBlock* post = block->createAnonymousBlock();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -