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

📄 inlineflowbox.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. * * 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 "InlineFlowBox.h"#include "CachedImage.h"#include "Document.h"#include "EllipsisBox.h"#include "GraphicsContext.h"#include "InlineTextBox.h"#include "HitTestResult.h"#include "RootInlineBox.h"#include "RenderBlock.h"#include "RenderInline.h"#include "RenderListMarker.h"#include "RenderTableCell.h"#include "RootInlineBox.h"#include "Text.h"#include <math.h>using namespace std;namespace WebCore {#ifndef NDEBUGInlineFlowBox::~InlineFlowBox(){    if (!m_hasBadChildList)        for (InlineBox* child = firstChild(); child; child = child->nextOnLine())            child->setHasBadParent();}#endifint InlineFlowBox::height() const{    const Font& font = renderer()->style(m_firstLine)->font();    int result = font.height();    bool strictMode = renderer()->document()->inStrictMode();    RenderBoxModelObject* box = boxModelObject();    result += box->borderTop() + box->paddingTop() + box->borderBottom() + box->paddingBottom();    if (!strictMode && !hasTextChildren() && !box->hasHorizontalBordersOrPadding()) {        int bottomOverflow = root()->bottomOverflow();        if (y() + result > bottomOverflow)            result = bottomOverflow - y();    }    return result;}int InlineFlowBox::getFlowSpacingWidth(){    int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->isInlineFlowBox())            totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();    }    return totWidth;}void InlineFlowBox::addToLine(InlineBox* child) {    ASSERT(!child->parent());    ASSERT(!child->nextOnLine());    ASSERT(!child->prevOnLine());    checkConsistency();    child->setParent(this);    if (!m_firstChild) {        m_firstChild = child;        m_lastChild = child;    } else {        m_lastChild->setNextOnLine(child);        child->setPrevOnLine(m_lastChild);        m_lastChild = child;    }    child->setFirstLineStyleBit(m_firstLine);    if (child->isText())        m_hasTextChildren = true;    if (child->renderer()->selectionState() != RenderObject::SelectionNone)        root()->setHasSelectedChildren(true);    checkConsistency();}void InlineFlowBox::removeChild(InlineBox* child){    checkConsistency();    if (!m_dirty)        dirtyLineBoxes();    root()->childRemoved(child);    if (child == m_firstChild)        m_firstChild = child->nextOnLine();    if (child == m_lastChild)        m_lastChild = child->prevOnLine();    if (child->nextOnLine())        child->nextOnLine()->setPrevOnLine(child->prevOnLine());    if (child->prevOnLine())        child->prevOnLine()->setNextOnLine(child->nextOnLine());        child->setParent(0);    checkConsistency();}void InlineFlowBox::deleteLine(RenderArena* arena){    InlineBox* child = firstChild();    InlineBox* next = 0;    while (child) {        ASSERT(this == child->parent());        next = child->nextOnLine();#ifndef NDEBUG        child->setParent(0);#endif        child->deleteLine(arena);        child = next;    }#ifndef NDEBUG    m_firstChild = 0;    m_lastChild = 0;#endif    removeLineBoxFromRenderObject();    destroy(arena);}void InlineFlowBox::removeLineBoxFromRenderObject(){    toRenderInline(renderer())->lineBoxes()->removeLineBox(this);}void InlineFlowBox::extractLine(){    if (!m_extracted)        extractLineBoxFromRenderObject();    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())        child->extractLine();}void InlineFlowBox::extractLineBoxFromRenderObject(){    toRenderInline(renderer())->lineBoxes()->extractLineBox(this);}void InlineFlowBox::attachLine(){    if (m_extracted)        attachLineBoxToRenderObject();    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())        child->attachLine();}void InlineFlowBox::attachLineBoxToRenderObject(){    toRenderInline(renderer())->lineBoxes()->attachLineBox(this);}void InlineFlowBox::adjustPosition(int dx, int dy){    InlineRunBox::adjustPosition(dx, dy);    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())        child->adjustPosition(dx, dy);}RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const{    return toRenderInline(renderer())->lineBoxes();}bool InlineFlowBox::onEndChain(RenderObject* endObject){    if (!endObject)        return false;        if (endObject == renderer())        return true;    RenderObject* curr = endObject;    RenderObject* parent = curr->parent();    while (parent && !parent->isRenderBlock()) {        if (parent->lastChild() != curr || parent == renderer())            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;    // The root inline box never has borders/margins/padding.    if (parent()) {        bool ltr = renderer()->style()->direction() == LTR;        // Check to see if all initial lines are unconstructed.  If so, then        // we know the inline began on this line (unless we are a continuation).        RenderLineBoxList* lineBoxList = rendererLineBoxes();        if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineContinuation()) {            if (ltr && lineBoxList->firstLineBox() == this)                includeLeftEdge = true;            else if (!ltr && lineBoxList->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 (!lineBoxList->lastLineBox()->isConstructed()) {            RenderInline* inlineFlow = toRenderInline(renderer());            if (ltr) {                if (!nextLineBox() &&                    ((lastLine && !inlineFlow->continuation()) || nextOnLineExists() || onEndChain(endObject)))                    includeRightEdge = true;            } else {                if ((!prevLineBox() || prevLineBox()->isConstructed()) &&                    ((lastLine && !inlineFlow->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 xPos, int& leftPosition, int& rightPosition, bool& needsWordSpacing){    // Set our x position.    setX(xPos);    int boxShadowLeft = 0;    int boxShadowRight = 0;    for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {        boxShadowLeft = min(boxShadow->x - boxShadow->blur, boxShadowLeft);        boxShadowRight = max(boxShadow->x + boxShadow->blur, boxShadowRight);    }    leftPosition = min(xPos + boxShadowLeft, leftPosition);    int startX = xPos;    xPos += borderLeft() + paddingLeft();        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {        if (curr->renderer()->isText()) {            InlineTextBox* text = static_cast<InlineTextBox*>(curr);            RenderText* rt = toRenderText(text->renderer());            if (rt->textLength()) {                if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))                    xPos += rt->style(m_firstLine)->font().wordSpacing();                needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);            }            text->setX(xPos);                        int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));                        // If letter-spacing is negative, we should factor that into right overflow. (Even in RTL, letter-spacing is            // applied to the right, so this is not an issue with left overflow.            int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing());                        int leftGlyphOverflow = -strokeOverflow;            int rightGlyphOverflow = strokeOverflow - letterSpacing;                        int visualOverflowLeft = leftGlyphOverflow;            int visualOverflowRight = rightGlyphOverflow;            for (ShadowData* shadow = rt->style()->textShadow(); shadow; shadow = shadow->next) {                visualOverflowLeft = min(visualOverflowLeft, shadow->x - shadow->blur + leftGlyphOverflow);                visualOverflowRight = max(visualOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow);            }                        leftPosition = min(xPos + visualOverflowLeft, leftPosition);            rightPosition = max(xPos + text->width() + visualOverflowRight, rightPosition);            m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), (int)m_maxHorizontalVisualOverflow);            xPos += text->width();        } else {            if (curr->renderer()->isPositioned()) {                if (curr->renderer()->parent()->style()->direction() == LTR)                    curr->setX(xPos);                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 from the root line box).                    curr->setX(root()->block()->width() - xPos);                continue; // The positioned object has no effect on the width.            }            if (curr->renderer()->isRenderInline()) {                InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);                xPos += flow->marginLeft();                xPos = flow->placeBoxesHorizontally(xPos, leftPosition, rightPosition, needsWordSpacing);                xPos += flow->marginRight();            } else if (!curr->renderer()->isListMarker() || static_cast<RenderListMarker*>(curr->renderer())->isInside()) {                xPos += curr->boxModelObject()->marginLeft();                curr->setX(xPos);                leftPosition = min(xPos + toRenderBox(curr->renderer())->overflowLeft(false), leftPosition);                rightPosition = max(xPos + toRenderBox(curr->renderer())->overflowWidth(false), rightPosition);                xPos += curr->width() + curr->boxModelObject()->marginRight();            }        }    }    xPos += borderRight() + paddingRight();    setWidth(xPos - startX);    rightPosition = max(x() + width() + boxShadowRight, rightPosition);    return xPos;}int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock)

⌨️ 快捷键说明

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