📄 render_object.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: render_object.cpp,v 1.120.2.2 2003/05/16 14:56:48 pchitescu Exp $ */#include "render_object.h"#include "dom_nodeimpl.h"#include "render_box.h"#include "render_flow.h"#include "render_style.h"#include "render_table.h"#include "render_list.h"#include "render_style.h"#include "render_root.h"#include "render_hr.h"#include "misc/loader.h"#include <kdebug.h>#include <qnamespace.h>#include <qpainter.h>#include <qcolor.h>#include <qpen.h>#include <qsize.h>#include <assert.h>using namespace DOM;using namespace khtml;RenderObject *RenderObject::createObject(DOM::NodeImpl *node){ RenderStyle *style = node->style(); RenderObject *o = 0; switch(style->display()) { case INLINE: case BLOCK: o = new RenderFlow(); break; case LIST_ITEM: o = new RenderListItem(); break; case RUN_IN: case COMPACT: case MARKER: break; case KONQ_RULER: o = new RenderHR(); break; case TABLE: case INLINE_TABLE: // ### set inline/block right //kdDebug( 6040 ) << "creating RenderTable" << endl; o = new RenderTable(); break; case TABLE_ROW_GROUP: case TABLE_HEADER_GROUP: case TABLE_FOOTER_GROUP: o = new RenderTableSection(); break; case TABLE_ROW: o = new RenderTableRow(); break; case TABLE_COLUMN_GROUP: case TABLE_COLUMN: o = new RenderTableCol(); break; case TABLE_CELL: o = new RenderTableCell(); break; case TABLE_CAPTION: o = new RenderTableCaption(); break; case NONE: return 0; } if(o) o->setStyle(style); return o;}RenderObject::RenderObject(){ m_style = 0; m_layouted = false; m_parsing = false; m_minMaxKnown = false; m_parent = 0; m_previous = 0; m_next = 0; m_floating = false; m_positioned = false; m_relPositioned = false; m_printSpecial = false; m_containsPositioned = false; m_isAnonymous = false; m_isText = false; m_inline = true; m_replaced = false; m_visible = true; m_containsWidget = false; m_containsOverhangingFloats = false; m_hasFirstLine = false; m_verticalPosition = PositionUndefined;}RenderObject::~RenderObject(){ if(m_style->backgroundImage()) m_style->backgroundImage()->deref(this); if (m_style) m_style->deref();}void RenderObject::addChild(RenderObject* , RenderObject *){ ASSERT(0);}RenderObject* RenderObject::removeChildNode(RenderObject* ){ ASSERT(0); return 0;}void RenderObject::removeChild(RenderObject* ){ ASSERT(0);}void RenderObject::appendChildNode(RenderObject*){ ASSERT(0);}void RenderObject::insertChildNode(RenderObject*, RenderObject*){ ASSERT(0);}RenderObject *RenderObject::containingBlock() const{ if(isTableCell()) { return static_cast<const RenderTableCell *>(this)->table(); } RenderObject *o = parent(); if(m_style->position() == FIXED) { while ( o && !o->isRoot() ) o = o->parent(); } else if(m_style->position() == ABSOLUTE) { while (o && o->style()->position() == STATIC && !o->isHtml() && !o->isRoot()) o = o->parent(); } else { while(o && o->isInline()) o = o->parent(); } // this is just to make sure we return a valid element. // the case below should never happen... if(!o) { if(!isRoot()) { //assert ( false ); kdDebug( 6040 ) << renderName() << "(RenderObject): No containingBlock!" << endl; } return const_cast<RenderObject *>(this); } else return o;}short RenderObject::containingBlockWidth() const{ // ### return containingBlock()->contentWidth();}int RenderObject::containingBlockHeight() const{ // ### return containingBlock()->contentHeight();}void RenderObject::drawBorder(QPainter *p, int x1, int y1, int x2, int y2, int width, BorderSide s, QColor c, const QColor& textcolor, EBorderStyle style, bool sb1, bool sb2, int adjbw1, int adjbw2, bool invalidisInvert){ if(style == DOUBLE && width < 3) style = SOLID; if(!c.isValid()) { if(invalidisInvert) { p->setRasterOp(Qt::XorROP); c = Qt::white; } else { if(style == INSET || style == OUTSET || style == RIDGE || style == GROOVE) c.setRgb(238, 238, 238); else c = textcolor; } } int half = width/2; switch(style) { case BNONE: case BHIDDEN: // should not happen if(invalidisInvert && p->rasterOp() == Qt::XorROP) p->setRasterOp(Qt::CopyROP); return; case DOTTED: p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DotLine)); /* nobreak; */ case DASHED: if(style == DASHED) p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DashLine)); switch(s) { case BSTop: y1 += half; y2 += half; break; case BSBottom: y1 -= half + (width % 2); y2 -= half + (width % 2); break; case BSLeft: x1 += half; x2 += half; y1 += width; y2 -= width; break; case BSRight: x1 -= half + (width % 2); x2 -= half + (width % 2); y2 -= width; y1 += width; break; } p->drawLine(x1, y1, x2, y2); break; case DOUBLE: { p->setPen(Qt::NoPen); p->setBrush(c); int w = (width+1)/3; switch(s) { case BSTop: p->drawRect(x1, y1, x2-x1, w); p->drawRect(x1+(sb1 ? 0 : width), y1+width-w, x2-x1-(sb1 ? 0 : width)-(sb2 ? 0 : width), w); break; case BSBottom: p->drawRect(x1, y1-w, x2-x1, w); p->drawRect(x1+(sb1 ? 0 : width-w), y1-width, x2-x1-(sb1 ? 0 : width-w)-(sb2 ? 0 : width-w), w); break; case BSLeft: p->drawRect(x1, y1, w, y2-y1); p->drawRect(x1+width-w, y1+width-w, w, y2-y1-2*width+2*w); break; case BSRight: p->drawRect(x1-w, y1, w, y2-y1); p->drawRect(x1-width, y1+width-w, w, y2-y1-2*width+2*w); break; } break; } case RIDGE: // could be more efficient. but maybe current code is already faster than // drawing two small rectangles? // disadvantage is that current edges doesn't look right because of reverse // drawing order drawBorder(p, x1, y1, x2, y2, width, s, c, textcolor, INSET, true, true, adjbw1, adjbw2); drawBorder(p, x1, y1, x2, y2, half, s, c, textcolor, OUTSET, true, true, adjbw1/2, adjbw2/2); break; case GROOVE: drawBorder(p, x1, y1, x2, y2, width, s, c, textcolor, OUTSET, true, true, adjbw1, adjbw2); drawBorder(p, x1, y1, x2, y2, half, s, c, textcolor, INSET, true, true, adjbw1/2, adjbw2/2); break; case INSET: if(s == BSTop || s == BSLeft) c = c.dark(); /* nobreak; */ case OUTSET: if(style == OUTSET && (s == BSBottom || s == BSRight)) c = c.dark(); if(s == BSTop || s == BSLeft) sb2 = true; else sb1 = true; /* nobreak; */ case SOLID: // ###: make this shitty code faster (Dirk) // use convex polygon drawing (40% faster) // only draw expensive edges if its actually visible (colors / visibility different, see sb1 / sb2) QPointArray tri(3); p->setPen(Qt::NoPen); p->setBrush(c); switch(s) { case BSTop: if(width) { if(sb1) { tri.setPoints(3, x1, y1, x1+adjbw1, y1, x1+adjbw1, y1+width); p->drawPolygon(tri); } if(sb2) { tri.setPoints(3, x2-adjbw2, y2, x2, y2, x2-adjbw2, y2+width); p->drawPolygon(tri); } p->drawRect(x1+adjbw1, y1, x2-x1-adjbw1-(sb2 ? adjbw2 : 0), width); } else p->drawRect(x1, y1, x2-x1, 0); break; case BSBottom: if(width) { if(sb1) { tri.setPoints(3, x1, y1, x1+adjbw1, y1, x1+adjbw1, y1-width); p->drawPolygon(tri); } if(sb2) { tri.setPoints(3, x2-adjbw2, y2-width, x2-adjbw2, y2, x2, y2); p->drawPolygon(tri); } p->drawRect(x1+(sb1 ? adjbw1 : 0), y1-width, x2-x1-(sb1 ? adjbw1 : 0)-adjbw2, width); } else p->drawRect(x1, y1, x2-x1, 0); break; break; case BSLeft: if(width) { if(sb1) { tri.setPoints(3, x1, y1, x1, y1+adjbw1, x1+width, y1+adjbw1); p->drawPolygon(tri); } if(sb2) { tri.setPoints(3, x2, y2-adjbw2, x2, y2, x2+width, y2-adjbw2); p->drawPolygon(tri); } p->drawRect(x1, y1+(sb1 ? adjbw1 : 0), width, y2-y1-(sb1 ? adjbw1:0)-adjbw2); } else p->drawRect(x1, y1+adjbw1, 0, y2-y1); break; case BSRight: if(width) { if(sb1) { tri.setPoints(3, x1, y1, x1, y1+adjbw1, x1-width, y1+adjbw1); p->drawPolygon(tri); } if(sb2) { tri.setPoints(3, x2, y2, x2, y2-adjbw2, x2-width, y2-adjbw2); p->drawPolygon(tri); } p->drawRect(x1-width, y1+adjbw1, width, y2-y1-adjbw1-(sb2 ? adjbw2 : 0)); } else p->drawRect(x1, y1+adjbw1, 0, y2-y1); break; } break; } if(invalidisInvert && p->rasterOp() == Qt::XorROP)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -