📄 renderobject.cpp
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2004, 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 "RenderObject.h"#include "AXObjectCache.h"#include "CSSStyleSelector.h"#include "FloatQuad.h"#include "Frame.h"#include "FrameView.h"#include "GraphicsContext.h"#include "HTMLNames.h"#include "HitTestResult.h"#include "Page.h"#include "RenderArena.h"#include "RenderCounter.h"#include "RenderFlexibleBox.h"#include "RenderImageGeneratedContent.h"#include "RenderInline.h"#include "RenderListItem.h"#include "RenderTableCell.h"#include "RenderTableCol.h"#include "RenderTableRow.h"#include "RenderTheme.h"#include "RenderView.h"#include "TransformState.h"#include <algorithm>#include <stdio.h>#include <wtf/RefCountedLeakCounter.h>#include <wtf/UnusedParam.h>#if USE(ACCELERATED_COMPOSITING)#include "RenderLayerCompositor.h"#endif#if ENABLE(WML)#include "WMLNames.h"#endifusing namespace std;namespace WebCore {using namespace HTMLNames;#ifndef NDEBUGstatic void* baseOfRenderObjectBeingDeleted;#endifbool RenderObject::s_affectsParentBlock = false;void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw(){ return renderArena->allocate(sz);}void RenderObject::operator delete(void* ptr, size_t sz){ ASSERT(baseOfRenderObjectBeingDeleted == ptr); // Stash size where destroy can find it. *(size_t *)ptr = sz;}RenderObject* RenderObject::createObject(Node* node, RenderStyle* style){ Document* doc = node->document(); RenderArena* arena = doc->renderArena(); // Minimal support for content properties replacing an entire element. // Works only if we have exactly one piece of content and it's a URL. // Otherwise acts as if we didn't support this feature. const ContentData* contentData = style->contentData(); if (contentData && !contentData->m_next && contentData->m_type == CONTENT_OBJECT && doc != node) { RenderImageGeneratedContent* image = new (arena) RenderImageGeneratedContent(node); image->setStyle(style); if (StyleImage* styleImage = contentData->m_content.m_image) image->setStyleImage(styleImage); return image; } RenderObject* o = 0; switch (style->display()) { case NONE: break; case INLINE: o = new (arena) RenderInline(node); break; case BLOCK: o = new (arena) RenderBlock(node); break; case INLINE_BLOCK: o = new (arena) RenderBlock(node); break; case LIST_ITEM: o = new (arena) RenderListItem(node); break; case RUN_IN: case COMPACT: o = new (arena) RenderBlock(node); break; case TABLE: case INLINE_TABLE: o = new (arena) RenderTable(node); break; case TABLE_ROW_GROUP: case TABLE_HEADER_GROUP: case TABLE_FOOTER_GROUP: o = new (arena) RenderTableSection(node); break; case TABLE_ROW: o = new (arena) RenderTableRow(node); break; case TABLE_COLUMN_GROUP: case TABLE_COLUMN: o = new (arena) RenderTableCol(node); break; case TABLE_CELL: o = new (arena) RenderTableCell(node); break; case TABLE_CAPTION: o = new (arena) RenderBlock(node); break; case BOX: case INLINE_BOX: o = new (arena) RenderFlexibleBox(node); break; } return o;}#ifndef NDEBUG static WTF::RefCountedLeakCounter renderObjectCounter("RenderObject");#endifRenderObject::RenderObject(Node* node) : CachedResourceClient() , m_style(0) , m_node(node) , m_parent(0) , m_previous(0) , m_next(0)#ifndef NDEBUG , m_hasAXObject(false) , m_setNeedsLayoutForbidden(false)#endif , m_needsLayout(false) , m_needsPositionedMovementLayout(false) , m_normalChildNeedsLayout(false) , m_posChildNeedsLayout(false) , m_prefWidthsDirty(false) , m_floating(false) , m_positioned(false) , m_relPositioned(false) , m_paintBackground(false) , m_isAnonymous(node == node->document()) , m_isText(false) , m_isBox(false) , m_inline(true) , m_replaced(false) , m_isDragging(false) , m_hasLayer(false) , m_hasOverflowClip(false) , m_hasTransform(false) , m_hasReflection(false) , m_hasOverrideSize(false) , m_hasCounterNodeMap(false) , m_everHadLayout(false) , m_childrenInline(false) , m_topMarginQuirk(false) , m_bottomMarginQuirk(false) , m_hasMarkupTruncation(false) , m_selectionState(SelectionNone) , m_hasColumns(false) , m_cellWidthChanged(false) , m_replacedHasOverflow(false){#ifndef NDEBUG renderObjectCounter.increment();#endif ASSERT(node);}RenderObject::~RenderObject(){ ASSERT(!node() || documentBeingDestroyed() || !document()->frame()->view() || document()->frame()->view()->layoutRoot() != this);#ifndef NDEBUG ASSERT(!m_hasAXObject); renderObjectCounter.decrement();#endif}bool RenderObject::isDescendantOf(const RenderObject* obj) const{ for (const RenderObject* r = this; r; r = r->m_parent) { if (r == obj) return true; } return false;}bool RenderObject::isBody() const{ return node() && node()->hasTagName(bodyTag);}bool RenderObject::isHR() const{ return node() && node()->hasTagName(hrTag);}bool RenderObject::isHTMLMarquee() const{ return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);}static void updateListMarkerNumbers(RenderObject* child){ for (RenderObject* r = child; r; r = r->nextSibling()) if (r->isListItem()) static_cast<RenderListItem*>(r)->updateValue();}void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild){ RenderObjectChildList* children = virtualChildren(); ASSERT(children); if (!children) return; bool needsTable = false; if (newChild->isListItem()) updateListMarkerNumbers(beforeChild ? beforeChild : children->lastChild()); else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP) needsTable = !isTable(); else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION) needsTable = !isTable(); else if (newChild->isTableSection()) needsTable = !isTable(); else if (newChild->isTableRow()) needsTable = !isTableSection(); else if (newChild->isTableCell()) { needsTable = !isTableRow(); // I'm not 100% sure this is the best way to fix this, but without this // change we recurse infinitely when trying to render the CSS2 test page: // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html. // See Radar 2925291. if (needsTable && isTableCell() && !children->firstChild() && !newChild->isTableCell()) needsTable = false; } if (needsTable) { RenderTable* table; RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children->lastChild(); if (afterChild && afterChild->isAnonymous() && afterChild->isTable()) table = static_cast<RenderTable*>(afterChild); else { table = new (renderArena()) RenderTable(document() /* is anonymous */); RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(style()); newStyle->setDisplay(TABLE); table->setStyle(newStyle.release()); addChild(table, beforeChild); } table->addChild(newChild); } else { // Just add it... children->insertChildNode(this, newChild, beforeChild); } if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) { RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText(); if (textToTransform) toRenderText(newChild)->setText(textToTransform.release(), true); }}void RenderObject::removeChild(RenderObject* oldChild){ RenderObjectChildList* children = virtualChildren(); ASSERT(children); if (!children) return; // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on // layout anyway). if (oldChild->isFloatingOrPositioned()) toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists(); children->removeChildNode(this, oldChild);}RenderObject* RenderObject::nextInPreOrder() const{ if (RenderObject* o = firstChild()) return o; return nextInPreOrderAfterChildren();}RenderObject* RenderObject::nextInPreOrderAfterChildren() const{ RenderObject* o; if (!(o = nextSibling())) { o = parent(); while (o && !o->nextSibling()) o = o->parent(); if (o) o = o->nextSibling(); } return o;}RenderObject* RenderObject::nextInPreOrder(RenderObject* stayWithin) const{ if (RenderObject* o = firstChild()) return o; return nextInPreOrderAfterChildren(stayWithin);}RenderObject* RenderObject::nextInPreOrderAfterChildren(RenderObject* stayWithin) const{ if (this == stayWithin) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -