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

📄 render_block.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * 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 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * *///#define DEBUG//#define DEBUG_LAYOUT//#define BOX_DEBUG//#define FLOAT_DEBUG#include <kdebug.h>#include "rendering/render_text.h"#include "rendering/render_table.h"#include "rendering/render_canvas.h"#include "xml/dom_nodeimpl.h"#include "xml/dom_docimpl.h"#include "xml/dom_position.h"#include "xml/dom_selection.h"#include "html/html_formimpl.h"#include "render_block.h"#include "khtmlview.h"#include "khtml_part.h"#include "htmltags.h"using namespace DOM;namespace khtml {RenderBlock::RenderBlock(DOM::NodeImpl* node):RenderFlow(node){    m_childrenInline = true;    m_floatingObjects = 0;    m_positionedObjects = 0;    m_pre = false;    m_firstLine = false;    m_linesAppended = false;    m_hasMarkupTruncation = false;    m_clearStatus = CNONE;    m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;    m_topMarginQuirk = m_bottomMarginQuirk = false;    m_overflowHeight = 0;    m_overflowWidth = 0;}RenderBlock::~RenderBlock(){    delete m_floatingObjects;    delete m_positionedObjects;}void RenderBlock::setStyle(RenderStyle* _style){    setReplaced(_style->isDisplayReplacedType());    RenderFlow::setStyle(_style);    m_pre = false;    if (_style->whiteSpace() == PRE)        m_pre = true;    // ### we could save this call when the change only affected    // non inherited properties    RenderObject *child = firstChild();    while (child != 0)    {        if (child->isAnonymousBlock())        {            RenderStyle* newStyle = new (renderArena()) RenderStyle();            newStyle->inheritFrom(style());            newStyle->setDisplay(BLOCK);            child->setStyle(newStyle);        }        child = child->nextSibling();    }    m_lineHeight = -1;    // Update pseudos for :before and :after now.    updatePseudoChild(RenderStyle::BEFORE, firstChild());    updatePseudoChild(RenderStyle::AFTER, lastChild());}void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild){    // Make sure we don't append things after :after-generated content if we have it.    if (!beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER)        beforeChild = lastChild();        bool madeBoxesNonInline = FALSE;    // If the requested beforeChild is not one of our children, then this is most likely because    // there is an anonymous block box within this object that contains the beforeChild. So    // just insert the child into the anonymous block box instead of here.    if (beforeChild && beforeChild->parent() != this) {        KHTMLAssert(beforeChild->parent());        KHTMLAssert(beforeChild->parent()->isAnonymousBlock());        if (newChild->isInline()) {            beforeChild->parent()->addChild(newChild,beforeChild);            return;        }        else if (beforeChild->parent()->firstChild() != beforeChild)            return beforeChild->parent()->addChild(newChild, beforeChild);        else            return addChildToFlow(newChild, beforeChild->parent());    }    // prevent elements that haven't received a layout yet from getting painted by pushing    // them far above the top of the page    if (!newChild->isInline())        newChild->setPos(newChild->xPos(), -500000);    // A block has to either have all of its children inline, or all of its children as blocks.    // So, if our children are currently inline and a block child has to be inserted, we move all our    // inline children into anonymous block boxes    if ( m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned() )    {        // This is a block with inline content. Wrap the inline content in anonymous blocks.        makeChildrenNonInline(beforeChild);        madeBoxesNonInline = true;                if (beforeChild && beforeChild->parent() != this) {            beforeChild = beforeChild->parent();            KHTMLAssert(beforeChild->isAnonymousBlock());            KHTMLAssert(beforeChild->parent() == this);        }    }    else if (!m_childrenInline && !newChild->isFloatingOrPositioned())    {        // If we're inserting an inline child but all of our children are blocks, then we have to make sure        // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise        // a new one is created and inserted into our list of children in the appropriate position.        if (newChild->isInline()) {            if (beforeChild) {                if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousBlock()) {                    beforeChild->previousSibling()->addChild(newChild);                    return;                }            }            else {                if (m_last && m_last->isAnonymousBlock()) {                    m_last->addChild(newChild);                    return;                }            }            // no suitable existing anonymous box - create a new one            RenderBlock* newBox = createAnonymousBlock();            RenderBox::addChild(newBox,beforeChild);            newBox->addChild(newChild);            newBox->setPos(newBox->xPos(), -500000);            return;        }    }    RenderBox::addChild(newChild,beforeChild);    // ### care about aligned stuff    if ( madeBoxesNonInline )        removeLeftoverAnonymousBoxes();}static void getInlineRun(RenderObject* start, RenderObject* stop,                         RenderObject*& inlineRunStart,                         RenderObject*& inlineRunEnd){    // Beginning at |start| we find the largest contiguous run of inlines that    // we can.  We denote the run with start and end points, |inlineRunStart|    // and |inlineRunEnd|.  Note that these two values may be the same if    // we encounter only one inline.    //    // We skip any non-inlines we encounter as long as we haven't found any    // inlines yet.    //    // |stop| indicates a non-inclusive stop point.  Regardless of whether |stop|    // is inline or not, we will not include it.  It's as though we encountered    // a non-inline.    inlineRunStart = inlineRunEnd = 0;    // Start by skipping as many non-inlines as we can.    RenderObject * curr = start;    while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))        curr = curr->nextSibling();    if (!curr)        return; // No more inline children to be found.    inlineRunStart = inlineRunEnd = curr;    bool sawInline = curr->isInline();        curr = curr->nextSibling();    while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != stop)) {        inlineRunEnd = curr;        if (curr->isInline())            sawInline = true;        curr = curr->nextSibling();    }        // Need to really see an inline in order to do any work.    if (!sawInline)        inlineRunStart = inlineRunEnd = 0;}void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint){    // makeChildrenNonInline takes a block whose children are *all* inline and it    // makes sure that inline children are coalesced under anonymous    // blocks.  If |insertionPoint| is defined, then it represents the insertion point for    // the new block child that is causing us to have to wrap all the inlines.  This    // means that we cannot coalesce inlines before |insertionPoint| with inlines following    // |insertionPoint|, because the new child is going to be inserted in between the inlines,    // splitting them.    KHTMLAssert(isInlineBlockOrInlineTable() || !isInline());    KHTMLAssert(!insertionPoint || insertionPoint->parent() == this);    m_childrenInline = false;    RenderObject *child = firstChild();    while (child) {        RenderObject *inlineRunStart, *inlineRunEnd;        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);        if (!inlineRunStart)            break;        child = inlineRunEnd->nextSibling();        RenderBlock* box = createAnonymousBlock();        insertChildNode(box, inlineRunStart);        RenderObject* o = inlineRunStart;        while(o != inlineRunEnd)        {            RenderObject* no = o;            o = no->nextSibling();            box->appendChildNode(removeChildNode(no));        }        box->appendChildNode(removeChildNode(inlineRunEnd));        box->close();        box->setPos(box->xPos(), -500000);    }}void RenderBlock::removeChildrenFromLineBoxes(){    // In the case where we do a collapse/merge from the destruction    // of a block in between two anonymous blocks with inlines (see removeChild in render_block.cpp),    // we have line boxes that need to have their parents nulled.    KHTMLAssert(!documentBeingDestroyed());    for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox())        for (InlineBox* child = box->firstChild(); child; child = child->nextOnLine())            child->remove();}void RenderBlock::removeChild(RenderObject *oldChild){    // If this child is a block, and if our previous and next siblings are    // both anonymous blocks with inline content, then we can go ahead and    // fold the inline content back together.    RenderObject* prev = oldChild->previousSibling();    RenderObject* next = oldChild->nextSibling();    bool mergedBlocks = false;    if (!documentBeingDestroyed() && !isInline() && !oldChild->isInline() && !oldChild->continuation() &&        prev && prev->isAnonymousBlock() && prev->childrenInline() &&        next && next->isAnonymousBlock() && next->childrenInline()) {        // Clean up the line box children inside |next|.        static_cast<RenderBlock*>(next)->removeChildrenFromLineBoxes();                // Take all the children out of the |next| block and put them in        // the |prev| block.        RenderObject* o = next->firstChild();        while (o) {            RenderObject* no = o;            o = no->nextSibling();            prev->appendChildNode(next->removeChildNode(no));            no->setNeedsLayoutAndMinMaxRecalc();        }        prev->setNeedsLayoutAndMinMaxRecalc();        // Nuke the now-empty block.        next->detach();        mergedBlocks = true;    }    RenderFlow::removeChild(oldChild);    if (mergedBlocks && prev && !prev->previousSibling() && !prev->nextSibling()) {

⌨️ 快捷键说明

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