📄 render_box.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) * * 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_box.cpp,v 1.138 2001/07/29 19:48:46 koivisto Exp $ */// -------------------------------------------------------------------------//#define DEBUG_LAYOUT#include "dom_string.h"#include <qpainter.h>#include <qfontmetrics.h>#include <qstack.h>#include "dom_node.h"#include "dom_textimpl.h"#include "dom_stringimpl.h"#include "dom_exception.h"#include "misc/helper.h"#include "htmlhashes.h"#include "khtmlview.h"#include "render_box.h"#include "render_style.h"#include "render_object.h"#include "render_text.h"#include "render_replaced.h"#include "render_root.h"#include <kdebug.h>#include <assert.h>#include "misc/loader.h"using namespace DOM;using namespace khtml;#define TABLECELLMARGIN -0x4000RenderBox::RenderBox() : RenderContainer(){ m_minWidth = -1; m_maxWidth = -1; m_width = m_height = 0; m_x = 0; m_y = 0; m_marginTop = 0; m_marginBottom = 0; m_marginLeft = 0; m_marginRight = 0;}void RenderBox::setStyle(RenderStyle *_style){ RenderObject::setStyle(_style); // ### move this into the parser. --> should work. Lars // if only horizontal position was defined, vertical should be 50% //if(!_style->backgroundXPosition().isVariable() && _style->backgroundYPosition().isVariable()) //style()->setBackgroundYPosition(Length(50, Percent)); switch(_style->position()) { case ABSOLUTE: case FIXED: setPositioned(true); break; default: setPositioned(false); if(_style->isFloating()) { setFloating(true); } else { if(_style->position() == RELATIVE) setRelPositioned(true); } }}RenderBox::~RenderBox(){ //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;}short RenderBox::contentWidth() const{ short w = m_width - style()->borderLeftWidth() - style()->borderRightWidth(); if(style()->hasPadding()) w -= paddingLeft() + paddingRight(); //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl; return w;}int RenderBox::contentHeight() const{ int h = m_height - style()->borderTopWidth() - style()->borderBottomWidth(); if(style()->hasPadding()) h -= paddingTop() + paddingBottom(); return h;}void RenderBox::setPos( int xPos, int yPos ){ m_x = xPos; m_y = yPos;#if 1 if(m_x != xPos || m_y != yPos) { bool cw = containsWidget(); if ( !cw && parent() && parent()->containsWidget() ) cw = true; if ( cw ) { int x,y; absolutePosition(x,y); // propagate position change to childs for(RenderObject *child = firstChild(); child; child = child->nextSibling()) { if(child->isWidget()) static_cast<RenderWidget*>(child)->placeWidget(x+child->xPos(),y+child->yPos()); } } }#endif}short RenderBox::width() const{ return m_width;}int RenderBox::height() const{ return m_height;}// --------------------- printing stuff -------------------------------void RenderBox::print(QPainter *p, int _x, int _y, int _w, int _h, int _tx, int _ty){ _tx += m_x; _ty += m_y; // default implementation. Just pass things through to the children RenderObject *child = firstChild(); while(child != 0) { child->print(p, _x, _y, _w, _h, _tx, _ty); child = child->nextSibling(); }}void RenderBox::setPixmap(const QPixmap &, const QRect&, CachedImage *image, bool *){ if(image && image->pixmap_size() == image->valid_rect().size() && parent()) repaint(); //repaint bg when it finished loading}void RenderBox::printBoxDecorations(QPainter *p,int, int _y, int, int _h, int _tx, int _ty){ //kdDebug( 6040 ) << renderName() << "::printDecorations()" << endl; int w = width(); int h = height() + borderTopExtra() + borderBottomExtra(); _ty -= borderTopExtra(); int my = QMAX(_ty,_y); int mh; if (_ty<_y) mh= QMAX(0,h-(_y-_ty)); else mh = QMIN(_h,h); if ( !root()->printingMode() ) printBackground(p, style()->backgroundColor(), style()->backgroundImage(), my, mh, _tx, _ty, w, h); if(style()->hasBorder()) printBorder(p, _tx, _ty, w, h, style());}void RenderBox::printBackground(QPainter *p, const QColor &c, CachedImage *bg, int clipy, int cliph, int _tx, int _ty, int w, int h){ if(c.isValid()) p->fillRect(_tx, clipy, w, cliph, c); // no progressive loading of the background image if(bg && bg->pixmap_size() == bg->valid_rect().size() && !bg->isTransparent() && !bg->isErrorImage()) { //kdDebug( 6040 ) << "printing bgimage at " << _tx << "/" << _ty << endl; // ### might need to add some correct offsets // ### use paddingX/Y //hacky stuff RenderStyle* sptr = style(); if ( isHtml() && firstChild() && !style()->backgroundImage() ) sptr = firstChild()->style(); int sx = 0; int sy = 0; int cw,ch; int cx,cy; int vpab = borderRight() + borderLeft(); int hpab = borderTop() + borderBottom(); // CSS2 chapter 14.2.1 if (sptr->backgroundAttachment()) { //scroll int pw = m_width - vpab; int ph = m_height - hpab; int pixw = bg->pixmap_size().width(); int pixh = bg->pixmap_size().height(); EBackgroundRepeat bgr = sptr->backgroundRepeat(); if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && w > pixw ) { cw = pixw; cx = _tx + sptr->backgroundXPosition().minWidth(pw-pixw); } else { cw = w-vpab; cx = _tx; sx = pixw - ((sptr->backgroundXPosition().minWidth(pw-pixw)) % pixw ); } cx += borderLeft(); if( (bgr == NO_REPEAT || bgr == REPEAT_X) && h > pixh ) { ch = pixh; cy = _ty + sptr->backgroundYPosition().minWidth(ph-pixh); } else { ch = h-hpab; cy = _ty; sy = pixh - ((sptr->backgroundYPosition().minWidth(ph-pixh)) % pixh ); } cy += borderTop(); } else { //fixed QRect vr = viewRect(); int pw = vr.width(); int ph = vr.height(); int pixw = bg->pixmap_size().width(); int pixh = bg->pixmap_size().height(); EBackgroundRepeat bgr = sptr->backgroundRepeat(); if( (bgr == NO_REPEAT || bgr == REPEAT_Y) && w > pixw ) { cw = pixw; cx = vr.x() + sptr->backgroundXPosition().minWidth(pw-pixw); } else { cw = pw; cx = vr.x(); sx = pixw - ((sptr->backgroundXPosition().minWidth(pw-pixw)) % pixw ); } if( (bgr == NO_REPEAT || bgr == REPEAT_X) && h > pixh ) { ch = pixh; cy = vr.y() + sptr->backgroundYPosition().minWidth(ph-pixh); } else { ch = ph; cy = vr.y(); sy = pixh - ((sptr->backgroundYPosition().minWidth(ph-pixh)) % pixh ); } QRect fix(cx,cy,cw,ch); QRect ele(_tx+borderLeft()+paddingLeft(),_ty+borderTop()+paddingTop(),w-vpab,h-hpab); QRect b = fix.intersect(ele); sx+=b.x()-cx; sy+=b.y()-cy; cx=b.x();cy=b.y();cw=b.width();ch=b.height(); }// kdDebug() << "cx="<<cx << " cy="<<cy<< " cw="<<cw << " ch="<<ch << " sx="<<sx << " sy="<<sy << endl; if (cw>0 && ch>0) p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c), sx, sy); }}void RenderBox::outlineBox(QPainter *p, int _tx, int _ty, const char *color){ p->setPen(QPen(QColor(color), 1, Qt::DotLine)); p->setBrush( Qt::NoBrush ); p->drawRect(_tx, _ty, m_width, m_height);}void RenderBox::calcClip(QPainter* p, int tx, int ty, const QRegion& old){ int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight(); int clipx = tx+bl; int clipy = ty+bt; int clipw = m_width-bl-br; int cliph = m_height-bt-bb; if (!style()->clipLeft().isVariable()) { int c=style()->clipLeft().width(m_width-bl-br); clipx+=c; clipw-=c; } if (!style()->clipRight().isVariable()) { clipw-=style()->clipRight().width(m_width-bl-br); } if (!style()->clipTop().isVariable()) { int c=style()->clipTop().width(m_height-bt-bb); clipy+=c; cliph-=c; } if (!style()->clipBottom().isVariable()) { cliph-=style()->clipBottom().width(m_height-bt-bb); }// kdDebug( 6040 ) << "setting clip("<<clipx<<","<<clipy<<","<<clipw<<","<<cliph<<")"<<endl; QRect cr(clipx,clipy,clipw,cliph); cr = p->xForm(cr); QRegion creg(cr); if (!old.isNull()) creg = old.intersect(creg); p->setClipRegion(creg); }void RenderBox::close(){ setParsing(false); calcWidth(); calcHeight(); calcMinMaxWidth(); if(containingBlockWidth() < m_minWidth && parent()) containingBlock()->updateSize(); else if(!isInline() || isReplaced()) { layout(); }}short RenderBox::containingBlockWidth() const{ if ( ( style()->htmlHacks() || isTable() ) && style()->flowAroundFloats() && containingBlock()->isFlow() && style()->width().isVariable()) return static_cast<RenderFlow*>(containingBlock())->lineWidth(m_y); else return containingBlock()->contentWidth();}bool RenderBox::absolutePosition(int &xPos, int &yPos, bool f){ if ( style()->position() == FIXED ) f = true; RenderObject *o = container(); if( o && o->absolutePosition(xPos, yPos, f)) { if(!isInline() || isReplaced()) xPos += m_x, yPos += m_y; if(isRelPositioned()) relativePositionOffset(xPos, yPos); return true; } else { xPos = yPos = 0; return false; }}void RenderBox::updateSize(){#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(RenderBox) " << this << " ::updateSize()" << endl;#endif int oldMin = m_minWidth; int oldMax = m_maxWidth; setMinMaxKnown(false); calcMinMaxWidth(); if ((isInline() || isFloating() || containsSpecial()) && parent()) { if (!isInline()) setLayouted(false); parent()->updateSize(); return; } if(m_minWidth > containingBlockWidth() || m_minWidth != oldMin || m_maxWidth != oldMax || isReplaced()) { setLayouted(false); if(containingBlock() != this) containingBlock()->updateSize(); } else updateHeight();}void RenderBox::updateHeight(){#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(RenderBox) " << this << " ::updateHeight()" << endl;#endif RenderObject* cb = containingBlock(); if (parsing()) { if (layouted()) { setLayouted(false); if(cb != this) cb->updateHeight(); } else { RenderRoot *rt = root(); if( rt ) rt->updateHeight(); } return; } if(!isInline() || isReplaced()) { int oldHeight = m_height; setLayouted(false); bool overhanging = hasOverhangingFloats(); layout(); overhanging |= hasOverhangingFloats(); if ( overhanging ) { if ( nextSibling() ) nextSibling()->setLayouted( false ); if(cb != this) cb->updateHeight(); } else if(m_height != oldHeight) { if(cb != this) cb->updateHeight(); } else { cb->repaint(); } }}void RenderBox::position(int x, int y, int, int, int, bool, bool){ m_x = x + marginLeft(); m_y = y; // ### paddings //m_width = width;}void RenderBox::repaint(){ //kdDebug( 6040 ) << "repaint!" << endl; int ow = style() ? style()->outlineWidth() : 0; repaintRectangle(-ow, -ow, m_width+ow*2, m_height+ow*2);}void RenderBox::repaintRectangle(int x, int y, int w, int h, bool f){ x += m_x; y += m_y; if (style()->position()==FIXED) f=true; // kdDebug( 6040 ) << "RenderBox(" << renderName() << ")::repaintRectangle (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl; RenderObject *o = container(); if( o ) o->repaintRectangle(x, y, w, h, f);}void RenderBox::relativePositionOffset(int &tx, int &ty){ if(!style()->left().isVariable()) tx += style()->left().width(containingBlockWidth()); else if(!style()->right().isVariable()) tx -= style()->right().width(containingBlockWidth()); if(!style()->top().isVariable()) { if (!style()->top().isPercent() || containingBlock()->style()->height().isFixed()) ty += style()->top().width(containingBlockHeight()); } else if(!style()->bottom().isVariable()) { if (!style()->bottom().isPercent() || containingBlock()->style()->height().isFixed()) ty -= style()->bottom().width(containingBlockHeight()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -