📄 render_object.cpp
字号:
/** * This file is part of the html renderer for KDE. * * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000-2003 Dirk Mueller (mueller@kde.org) * (C) 2002-2004 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 "rendering/render_object.h"#include "rendering/render_table.h"#include "rendering/render_list.h"#include "rendering/render_canvas.h"#include "rendering/render_block.h"#include "rendering/render_arena.h"#include "rendering/render_layer.h"#include "rendering/render_line.h"#include "rendering/render_inline.h"#include "rendering/render_text.h"#include "rendering/render_replaced.h"#include "rendering/render_generated.h"#include "rendering/counter_tree.h"#include "xml/dom_elementimpl.h"#include "xml/dom_docimpl.h"#include "dom/dom_doc.h"#include "misc/htmlhashes.h"#include "misc/loader.h"#include <kdebug.h>#include <kglobal.h>#include <qpainter.h>#include "khtmlview.h"#include <khtml_part.h>#include <assert.h>using namespace DOM;using namespace khtml;#define RED_LUMINOSITY 30#define GREEN_LUMINOSITY 59#define BLUE_LUMINOSITY 11#define INTENSITY_FACTOR 25#define LIGHT_FACTOR 0#define LUMINOSITY_FACTOR 75#define MAX_COLOR 255#define COLOR_DARK_THRESHOLD 51#define COLOR_LIGHT_THRESHOLD 204#define COLOR_LITE_BS_FACTOR 45#define COLOR_LITE_TS_FACTOR 70#define COLOR_DARK_BS_FACTOR 30#define COLOR_DARK_TS_FACTOR 50#define LIGHT_GRAY qRgb(192, 192, 192)#define DARK_GRAY qRgb(96, 96, 96)#ifndef NDEBUGstatic void *baseOfRenderObjectBeingDeleted;#endifvoid* 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 detach can find it. *(size_t *)ptr = sz;}RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* style){ RenderObject *o = 0; khtml::RenderArena* arena = node->getDocument()->renderArena(); switch(style->display()) { case NONE: break; case INLINE: case INLINE_BLOCK: case BLOCK: // In compat mode, if <td> has a display of block, build a table cell instead. // This corrects erroneous HTML. A better fix would be to implement full-blown // CSS2 anonymous table render object construction, but until then, this will have // to suffice. -dwh if (style->display() == BLOCK && node->id() == ID_TD && style->htmlHacks()) o = new (arena) RenderTableCell(node); // In quirks mode if <table> has a display of block, make a table. If it has // a display of inline, make an inline-table. else if (node->id() == ID_TABLE && style->htmlHacks()) o = new (arena) RenderTable(node); else if (style->display() == INLINE) o = new (arena) RenderInline(node); else o = new (arena) RenderBlock(node); break; case TABLE_CAPTION: 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: style->setFlowAroundFloats(true); 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; } return o;}RenderObject::RenderObject(DOM::NodeImpl* node) : CachedObjectClient(), m_style( 0 ), m_node( node ), m_parent( 0 ), m_previous( 0 ), m_next( 0 ), m_verticalPosition( PositionUndefined ), m_needsLayout( false ), m_normalChildNeedsLayout( false ), m_markedForRepaint( false ), m_posChildNeedsLayout( false ), m_minMaxKnown( false ), m_floating( false ), m_positioned( false ), m_overhangingContents( false ), m_relPositioned( false ), m_paintBackground( false ), m_isAnonymous( node->isDocumentNode() ), m_recalcMinMax( false ), m_isText( false ), m_inline( true ), m_replaced( false ), m_mouseInside( false ), m_hasFirstLine( false ), m_isSelectionBorder( false ), m_isRoot( false ), m_afterPageBreak( false ), m_needsPageClear( false ), m_containsPageBreak( false ){ assert( node ); if (node->getDocument()->documentElement() == node) setIsRoot(true);}RenderObject::~RenderObject(){ if(m_style->backgroundImage()) m_style->backgroundImage()->deref(this); if (m_style) m_style->deref();}RenderObject* RenderObject::objectBelow() const{ RenderObject* obj = firstChild(); if ( !obj ) { obj = nextSibling(); if ( !obj ) { obj = parent(); while (obj && !obj->nextSibling()) obj = obj->parent(); if (obj) obj = obj->nextSibling(); } } return obj;}RenderObject* RenderObject::objectAbove() const{ RenderObject* obj = previousSibling(); if ( !obj ) return parent(); RenderObject* last = obj->lastChild(); while ( last ) { obj = last; last = last->lastChild(); } return obj;}/*bool RenderObject::isRoot() const{ return !isAnonymous() && element()->getDocument()->documentElement() == element();}*/bool RenderObject::isHR() const{ return element() && element()->id() == ID_HR;}bool RenderObject::isHTMLMarquee() const{ return element() && element()->renderer() == this && element()->id() == ID_MARQUEE;}void RenderObject::addChild(RenderObject* , RenderObject *){ KHTMLAssert(0);}RenderObject* RenderObject::removeChildNode(RenderObject* ){ KHTMLAssert(0); return 0;}void RenderObject::removeChild(RenderObject *o ){ setNeedsLayout(true); removeChildNode( o );}void RenderObject::appendChildNode(RenderObject*){ KHTMLAssert(0);}void RenderObject::insertChildNode(RenderObject*, RenderObject*){ KHTMLAssert(0);}static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject, RenderLayer*& beforeChild){ if (obj->layer()) { if (!beforeChild && newObject) { // We need to figure out the layer that follows newObject. We only do // this the first time we find a child layer, and then we update the // pointer values for newObject and beforeChild used by everyone else. beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject); newObject = 0; } parentLayer->addChild(obj->layer(), beforeChild); return; } for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) addLayers(curr, parentLayer, newObject, beforeChild);}void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject){ if (!parentLayer) return; RenderObject* object = newObject; RenderLayer* beforeChild = 0; ::addLayers(this, parentLayer, object, beforeChild);}void RenderObject::removeLayers(RenderLayer* parentLayer){ if (!parentLayer) return; if (layer()) { parentLayer->removeChild(layer()); return; } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) curr->removeLayers(parentLayer);}void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent){ if (!newParent) return; if (layer()) { if (oldParent) oldParent->removeChild(layer()); newParent->addChild(layer()); return; } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) curr->moveLayers(oldParent, newParent);}RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent){ // Error check the parent layer passed in. If it's null, we can't find anything. if (!parentLayer) return 0; // Step 1: Descend into our siblings trying to find the next layer. If we do find // a layer, and if its parent layer matches our desired parent layer, then we have // a match. for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild(); curr; curr = curr->nextSibling()) { RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false); if (nextLayer) { if (nextLayer->parent() == parentLayer) return nextLayer; return 0; } } // Step 2: If our layer is the desired parent layer, then we're finished. We didn't // find anything. RenderLayer* ourLayer = layer(); if (parentLayer == ourLayer) return 0; // Step 3: If we have a layer, then return that layer. It will be checked against // the desired parent layer in the for loop above. if (ourLayer) return ourLayer; // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that // follow us to see if we can locate a layer. if (checkParent && parent()) return parent()->findNextLayer(parentLayer, this, true); return 0;}RenderLayer* RenderObject::enclosingLayer() const{ const RenderObject* curr = this; while (curr) { RenderLayer *layer = curr->layer(); if (layer) return layer; curr = curr->parent(); } return 0;}int RenderObject::offsetLeft() const{ if ( isPositioned() ) return xPos(); if ( isBody() && style()->htmlHacks() ) return 0; int x = xPos(); if (isRelPositioned()) { int y = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -