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

📄 render_block.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * This file is part of the render object implementation for KHTML. * * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) *           (C) 1999-2003 Antti Koivisto (koivisto@kde.org) *           (C) 2002-2003 Dirk Mueller (mueller@kde.org) *           (C) 2003 Apple Computer, Inc. *           (C) 2004 Germain Garand (germain@ebooksfrance.org) *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) * * 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. * *///#define DEBUG//#define DEBUG_LAYOUT//#define BOX_DEBUG//#define FLOAT_DEBUG//#define PAGE_DEBUG#include <kdebug.h>#include "rendering/render_text.h"#include "rendering/render_table.h"#include "rendering/render_canvas.h"#include "rendering/render_layer.h"#include "rendering/render_block.h"#include "xml/dom_nodeimpl.h"#include "xml/dom_docimpl.h"#include "html/html_formimpl.h"#include "misc/htmltags.h"#include "khtmlview.h"using namespace DOM;namespace khtml {// -------------------------------------------------------------------------------------------------------// Our MarginInfo state used when laying out block children.RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom){    // Whether or not we can collapse our own margins with our children.  We don't do this    // if we had any border/padding (obviously), if we're the root or HTML elements, or if    // we're positioned, floating, a table cell.    m_canCollapseWithChildren = !block->isCanvas() && !block->isRoot() && !block->isPositioned() &&        !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();    m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) /*&& block->style()->marginTopCollapse() != MSEPARATE */;    // If any height other than auto is specified in CSS, then we don't collapse our bottom    // margins with our children's margins.  To do otherwise would be to risk odd visual    // effects when the children overflow out of the parent block and yet still collapse    // with it.  We also don't collapse if we have any bottom border/padding.    m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&        (block->style()->height().isVariable() && block->style()->height().value() == 0) /*&& block->style()->marginBottomCollapse() != MSEPARATE*/;    m_quirkContainer = block->isTableCell() || block->isBody() /*|| block->style()->marginTopCollapse() == MDISCARD ||        block->style()->marginBottomCollapse() == MDISCARD*/;    m_atTopOfBlock = true;    m_atBottomOfBlock = false;    m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;    m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;    m_selfCollapsingBlockClearedFloat = false;    m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;}// -------------------------------------------------------------------------------------------------------RenderBlock::RenderBlock(DOM::NodeImpl* node)    : RenderFlow(node){    m_childrenInline = true;    m_floatingObjects = 0;    m_positionedObjects = 0;    m_pre = false;    m_firstLine = false;    m_avoidPageBreak = 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 = ( _style->whiteSpace() == PRE );    // ### 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 RenderStyle();            newStyle->inheritFrom(style());            newStyle->setDisplay(BLOCK);            child->setStyle(newStyle);        }        child = child->nextSibling();    }    // Update pseudos for :before and :after now.    updatePseudoChildren();    // handled by close() during parsing    if (!document()->parsing())        updateFirstLetter();}void RenderBlock::updateFirstLetter(){    // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find    // an efficient way to check for that situation though before implementing anything.    RenderStyle * pseudoStyle;    if ( isTable() || !(pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LETTER)) )        return;    // Drill into inlines looking for our first text child.    RenderObject* currChild = firstChild();    while (currChild && currChild->needsLayout() && !currChild->isReplaced() && !currChild->isText())        currChild = currChild->firstChild();   if (currChild && currChild->isText() && !currChild->isBR()) {        bool update = (currChild->parent()->style()->styleType() == RenderStyle::FIRST_LETTER);        RenderObject* firstLetterContainer = update ? currChild->parent()->parent() : currChild->parent();        RenderText* textObj = static_cast<RenderText*>(currChild);        // Force inline display (except for floating first-letters)        pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);        pseudoStyle->setPosition( STATIC ); // CSS2 says first-letter can't be positioned.        if (update) {            firstLetterContainer->firstChild()->setStyle( pseudoStyle );            RenderStyle* newStyle = new RenderStyle();            newStyle->inheritFrom( pseudoStyle );            currChild->setStyle( newStyle );            return;        }        RenderObject* firstLetter = RenderFlow::createFlow(element(), pseudoStyle, renderArena() );        firstLetter->setIsAnonymous( true );        firstLetterContainer->addChild(firstLetter, firstLetterContainer->firstChild());        // The original string is going to be either a generated content string or a DOM node's        // string.  We want the original string before it got transformed in case first-letter has        // no text-transform or a different text-transform applied to it.        DOMStringImpl* oldText = textObj->originalString();        if (!oldText)            oldText = textObj->string();        if(oldText->l >= 1) {            oldText->ref();            unsigned int length = 0;            while ( length < oldText->l &&                    ( (oldText->s+length)->isSpace() || (oldText->s+length)->isPunct() ) )                length++;            if ( length < oldText->l &&                     !( (oldText->s+length)->isSpace() || (oldText->s+length)->isPunct() ))                length++;            RenderTextFragment* remainingText =                new (renderArena()) RenderTextFragment(textObj->node(), oldText, length, oldText->l-length);            remainingText->setIsAnonymous( textObj->isAnonymous() );            remainingText->setStyle(textObj->style());            if (remainingText->element())                remainingText->element()->setRenderer(remainingText);            RenderObject* nextObj = textObj->nextSibling();            firstLetterContainer->removeChild(textObj);            firstLetterContainer->addChild(remainingText, nextObj);            RenderTextFragment* letter =                new (renderArena()) RenderTextFragment(remainingText->node(), oldText, 0, length);            letter->setIsAnonymous( remainingText->isAnonymous() );            RenderStyle* newStyle = new RenderStyle();            newStyle->inheritFrom(pseudoStyle);            letter->setStyle(newStyle);            firstLetter->addChild(letter);            oldText->deref();        }        firstLetter->close();    }}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);    if (!newChild->isText() && newChild->style()->position() != STATIC)        setOverhangingContents();    // 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;        }        else {            // We are adding another block child... if the current last child is an anonymous box            // then it needs to be closed.            // ### get rid of the closing thing altogether this will only work during initial parsing            if (lastChild() && lastChild()->isAnonymous()) {                lastChild()->close();            }        }    }    RenderBox::addChild(newChild,beforeChild);    // ### care about aligned stuff    if ( madeBoxesNonInline )        removeLeftoverAnonymousBoxes();}static void getInlineRun(RenderObject* start, RenderObject* stop,                         RenderObject*& inlineRunStart,                         RenderObject*& inlineRunEnd)

⌨️ 快捷键说明

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