📄 renderbox.cpp
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2005, 2006, 2007, 2008 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 "RenderBox.h"#include "CachedImage.h"#include "ChromeClient.h"#include "Document.h"#include "FrameView.h"#include "GraphicsContext.h"#include "htmlediting.h"#include "HTMLElement.h"#include "HTMLNames.h"#include "ImageBuffer.h"#include "FloatQuad.h"#include "Frame.h"#include "Page.h"#include "RenderArena.h"#include "RenderFlexibleBox.h"#include "RenderInline.h"#include "RenderLayer.h"#include "RenderTableCell.h"#include "RenderTheme.h"#include "RenderView.h"#include "TransformState.h"#include <algorithm>#include <math.h>#if ENABLE(WML)#include "WMLNames.h"#endifusing namespace std;namespace WebCore {using namespace HTMLNames;// Used by flexible boxes when flexing this element.typedef WTF::HashMap<const RenderBox*, int> OverrideSizeMap;static OverrideSizeMap* gOverrideSizeMap = 0;bool RenderBox::s_hadOverflowClip = false;RenderBox::RenderBox(Node* node) : RenderBoxModelObject(node) , m_marginLeft(0) , m_marginRight(0) , m_marginTop(0) , m_marginBottom(0) , m_minPrefWidth(-1) , m_maxPrefWidth(-1) , m_inlineBoxWrapper(0){ setIsBox();}RenderBox::~RenderBox(){}void RenderBox::destroy(){ // A lot of the code in this function is just pasted into // RenderWidget::destroy. If anything in this function changes, // be sure to fix RenderWidget::destroy() as well. if (hasOverrideSize()) gOverrideSizeMap->remove(this); if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent())) RenderBlock::removePercentHeightDescendant(this); RenderBoxModelObject::destroy();}void RenderBox::removeFloatingOrPositionedChildFromBlockLists(){ ASSERT(isFloatingOrPositioned()); if (documentBeingDestroyed()) return; if (isFloating()) { RenderBlock* outermostBlock = containingBlock(); for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) { if (p->containsFloat(this)) outermostBlock = p; } if (outermostBlock) outermostBlock->markAllDescendantsWithFloatsForLayout(this, false); } if (isPositioned()) { RenderObject* p; for (p = parent(); p; p = p->parent()) { if (p->isRenderBlock()) toRenderBlock(p)->removePositionedObject(this); } }}void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle){ s_hadOverflowClip = hasOverflowClip(); if (style()) { // The background of the root element or the body element could propagate up to // the canvas. Just dirty the entire canvas when our style changes substantially. if (diff >= StyleDifferenceRepaint && node() && (node()->hasTagName(htmlTag) || node()->hasTagName(bodyTag))) view()->repaint(); else if (parent() && !isText()) { // Do a repaint with the old style first, e.g., for example if we go from // having an outline to not having an outline. if (diff == StyleDifferenceRepaintLayer) { layer()->repaintIncludingDescendants(); if (!(style()->clip() == newStyle->clip())) layer()->clearClipRectsIncludingDescendants(); } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < style()->outlineSize()) repaint(); } if (diff == StyleDifferenceLayout) { // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could // end up being destroyed. if (hasLayer()) { if (style()->position() != newStyle->position() || style()->zIndex() != newStyle->zIndex() || style()->hasAutoZIndex() != newStyle->hasAutoZIndex() || !(style()->clip() == newStyle->clip()) || style()->hasClip() != newStyle->hasClip() || style()->opacity() != newStyle->opacity() || style()->transform() != newStyle->transform()) layer()->repaintIncludingDescendants(); } else if (newStyle->hasTransform() || newStyle->opacity() < 1) { // If we don't have a layer yet, but we are going to get one because of transform or opacity, // then we need to repaint the old position of the object. repaint(); } // When a layout hint happens and an object's position style changes, we have to do a layout // to dirty the render tree using the old position value now. if (parent() && style()->position() != newStyle->position()) { markContainingBlocksForLayout(); if (style()->position() == StaticPosition) repaint(); if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition)) removeFloatingOrPositionedChildFromBlockLists(); } } } RenderBoxModelObject::styleWillChange(diff, newStyle);}void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle){ RenderBoxModelObject::styleDidChange(diff, oldStyle); if (needsLayout() && oldStyle && (oldStyle->height().isPercent() || oldStyle->minHeight().isPercent() || oldStyle->maxHeight().isPercent())) RenderBlock::removePercentHeightDescendant(this); // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the // new zoomed coordinate space. if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) { int left = scrollLeft(); if (left) { left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom(); setScrollLeft(left); } int top = scrollTop(); if (top) { top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom(); setScrollTop(top); } } // Set the text color if we're the body. if (isBody()) document()->setTextColor(style()->color());}void RenderBox::updateBoxModelInfoFromStyle(){ RenderBoxModelObject::updateBoxModelInfoFromStyle(); bool isRootObject = isRoot(); bool isViewObject = isRenderView(); // The root and the RenderView always paint their backgrounds/borders. if (isRootObject || isViewObject) setHasBoxDecorations(true); setPositioned(style()->position() == AbsolutePosition || style()->position() == FixedPosition); setFloating(!isPositioned() && style()->isFloating()); // We also handle <body> and <html>, whose overflow applies to the viewport. if (style()->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) { bool boxHasOverflowClip = true; if (isBody()) { // Overflow on the body can propagate to the viewport under the following conditions. // (1) The root element is <html>. // (2) We are the primary <body> (can be checked by looking at document.body). // (3) The root element has visible overflow. if (document()->documentElement()->hasTagName(htmlTag) && document()->body() == node() && document()->documentElement()->renderer()->style()->overflowX() == OVISIBLE) boxHasOverflowClip = false; } // Check for overflow clip. // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value. if (boxHasOverflowClip) { if (!s_hadOverflowClip) // Erase the overflow repaint(); setHasOverflowClip(); } } setHasTransform(style()->hasTransformRelatedProperty()); setHasReflection(style()->boxReflect());}void RenderBox::layout(){ ASSERT(needsLayout()); RenderObject* child = firstChild(); if (!child) { setNeedsLayout(false); return; } LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y())); while (child) { child->layoutIfNeeded(); ASSERT(!child->needsLayout()); child = child->nextSibling(); } statePusher.pop(); setNeedsLayout(false);}// More IE extensions. clientWidth and clientHeight represent the interior of an object// excluding border and scrollbar.int RenderBox::clientWidth() const{ return width() - borderLeft() - borderRight() - verticalScrollbarWidth();}int RenderBox::clientHeight() const{ return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();}// scrollWidth/scrollHeight will be the same as overflowWidth/overflowHeight unless the// object has overflow:hidden/scroll/auto specified and also has overflow.// FIXME: It's not completely clear how scrollWidth/Height should behave for // objects with visible overflow.int RenderBox::scrollWidth() const{ if (hasOverflowClip()) return layer()->scrollWidth(); return overflowWidth();}int RenderBox::scrollHeight() const{ if (hasOverflowClip()) return layer()->scrollHeight(); return overflowHeight();}int RenderBox::scrollLeft() const{ return hasOverflowClip() ? layer()->scrollXOffset() : 0;}int RenderBox::scrollTop() const{ return hasOverflowClip() ? layer()->scrollYOffset() : 0;}void RenderBox::setScrollLeft(int newLeft){ if (hasOverflowClip()) layer()->scrollToXOffset(newLeft);}void RenderBox::setScrollTop(int newTop){ if (hasOverflowClip()) layer()->scrollToYOffset(newTop);}void RenderBox::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool){ rects.append(IntRect(tx, ty, width(), height()));}void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool){ quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height())));}IntRect RenderBox::absoluteContentBox() const{ IntRect rect = contentBoxRect(); FloatPoint absPos = localToAbsolute(FloatPoint()); rect.move(absPos.x(), absPos.y()); return rect;}FloatQuad RenderBox::absoluteContentQuad() const{ IntRect rect = contentBoxRect(); return localToAbsoluteQuad(FloatRect(rect));}IntRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const{ IntRect box = borderBoundingBox(); adjustRectForOutlineAndShadow(box);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -