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

📄 render_line.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*** This file is part of the html renderer for KDE. * * 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., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */// -------------------------------------------------------------------------#include <kdebug.h>#include <assert.h>#include <qpainter.h>#include <kglobal.h>#include "rendering/render_flow.h"#include "rendering/render_text.h"#include "rendering/render_table.h"#include "rendering/render_inline.h"#include "rendering/render_block.h"#include "rendering/render_arena.h"#include "rendering/render_line.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;using namespace khtml;#ifndef NDEBUGstatic bool inInlineBoxDetach;#endifvoid InlineBox::detach(RenderArena* renderArena){    if (m_parent)        m_parent->removeFromLine(this);#ifndef NDEBUG    inInlineBoxDetach = true;#endif    delete this;#ifndef NDEBUG    inInlineBoxDetach = false;#endif    // Recover the size left there for us by operator delete and free the memory.    renderArena->free(*(size_t *)this, this);}void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw(){    return renderArena->allocate(sz);}void InlineBox::operator delete(void* ptr, size_t sz){    assert(inInlineBoxDetach);    // Stash size where detach can find it.    *(size_t *)ptr = sz;}RootInlineBox* InlineBox::root(){    if (m_parent)        return m_parent->root();    return static_cast<RootInlineBox*>(this);}InlineFlowBox::~InlineFlowBox(){    /* If we're destroyed, set the children free, and break their links */    while (m_firstChild)        removeFromLine(m_firstChild);}void InlineFlowBox::removeFromLine(InlineBox *child){    if (child == m_firstChild) {        m_firstChild = child->nextOnLine();    }    if (child == m_lastChild) {        m_lastChild = child->prevOnLine();    }    if (child->nextOnLine()) {        child->nextOnLine()->m_prev = child->prevOnLine();    }    if (child->prevOnLine()) {        child->prevOnLine()->m_next = child->nextOnLine();    }    child->setParent(0);}int InlineFlowBox::marginLeft() const{    if (!includeLeftEdge())        return 0;    RenderStyle* cstyle = object()->style();    Length margin = cstyle->marginLeft();    if (!margin.isVariable())        return (margin.isFixed() ? margin.value() : object()->marginLeft());    return 0;}int InlineFlowBox::marginRight() const{    if (!includeRightEdge())        return 0;    RenderStyle* cstyle = object()->style();    Length margin = cstyle->marginRight();    if (!margin.isVariable())        return (margin.isFixed() ? margin.value() : object()->marginRight());    return 0;}int InlineFlowBox::marginBorderPaddingLeft() const{    return marginLeft() + borderLeft() + paddingLeft();}int InlineFlowBox::marginBorderPaddingRight() const{    return marginRight() + borderRight() + paddingRight();}int InlineFlowBox::getFlowSpacingWidth() const{    int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->isInlineFlowBox())            totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();    }    return totWidth;}bool InlineFlowBox::nextOnLineExists(){    if (!parent())        return false;    if (nextOnLine())        return true;    return parent()->nextOnLineExists();}bool InlineFlowBox::prevOnLineExists(){    if (!parent())        return false;    if (prevOnLine())        return true;    return parent()->prevOnLineExists();}bool InlineFlowBox::onEndChain(RenderObject* endObject){    if (!endObject)        return false;    if (endObject == object())        return true;    RenderObject* curr = endObject;    RenderObject* parent = curr->parent();    while (parent && !parent->isRenderBlock()) {        if (parent->lastChild() != curr)            return false;        curr = parent;        parent = curr->parent();    }    return true;}void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject){    // All boxes start off open.  They will not apply any margins/border/padding on    // any side.    bool includeLeftEdge = false;    bool includeRightEdge = false;    RenderFlow* flow = static_cast<RenderFlow*>(object());    if (!flow->firstChild())        includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.    else if (parent()) { // The root inline box never has borders/margins/padding.        bool ltr = flow->style()->direction() == LTR;        // Check to see if all initial lines are unconstructed.  If so, then        // we know the inline began on this line.        if (!flow->firstLineBox()->isConstructed()) {            if (ltr && flow->firstLineBox() == this)                includeLeftEdge = true;            else if (!ltr && flow->lastLineBox() == this)                includeRightEdge = true;        }        // In order to determine if the inline ends on this line, we check three things:        // (1) If we are the last line and we don't have a continuation(), then we can        // close up.        // (2) If the last line box for the flow has an object following it on the line (ltr,        // reverse for rtl), then the inline has closed.        // (3) The line may end on the inline.  If we are the last child (climbing up        // the end object's chain), then we just closed as well.        if (!flow->lastLineBox()->isConstructed()) {            if (ltr) {                if (!nextLineBox() &&                    ((lastLine && !object()->continuation()) || nextOnLineExists()                     || onEndChain(endObject)))                    includeRightEdge = true;            }            else {                if ((!prevLineBox() || !prevLineBox()->isConstructed()) &&                    ((lastLine && !object()->continuation()) ||                     prevOnLineExists() || onEndChain(endObject)))                    includeLeftEdge = true;            }        }    }    setEdges(includeLeftEdge, includeRightEdge);    // Recur into our children.    for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {        if (currChild->isInlineFlowBox()) {            InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);            currFlow->determineSpacingForFlowBoxes(lastLine, endObject);        }    }}int InlineFlowBox::placeBoxesHorizontally(int x){    // Set our x position.    setXPos(x);    int startX = x;    x += borderLeft() + paddingLeft();    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->object()->isText()) {            InlineTextBox* text = static_cast<InlineTextBox*>(curr);            text->setXPos(x);            x += curr->width();        }        else {            if (curr->object()->isPositioned()) {                if (curr->object()->parent()->style()->direction() == LTR)                    curr->setXPos(x);                else {                    // Our offset that we cache needs to be from the edge of the right border box and                    // not the left border box.  We have to subtract |x| from the width of the block                    // (which can be obtained by walking up to the root line box).                    InlineBox* root = this;                    while (!root->isRootInlineBox())                        root = root->parent();                    curr->setXPos(root->object()->width()-x);                }                continue; // The positioned object has no effect on the width.            }            if (curr->object()->isInlineFlow()) {                InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);                x += flow->marginLeft();                x = flow->placeBoxesHorizontally(x);                x += flow->marginRight();            }            else {                x += curr->object()->marginLeft();                curr->setXPos(x);                x += curr->width() + curr->object()->marginRight();            }        }    }    x += borderRight() + paddingRight();    setWidth(x-startX);    return x;}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)

⌨️ 快捷键说明

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