📄 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) * Copyright (C) 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */// -------------------------------------------------------------------------//#define DEBUG_LAYOUT#include <qpainter.h>#include "rendering/render_box.h"#include "rendering/render_replaced.h"#include "rendering/render_canvas.h"#include "rendering/render_table.h"#include "render_flexbox.h"#include "render_arena.h"#include "misc/htmlhashes.h"#include "xml/dom_nodeimpl.h"#include "xml/dom_docimpl.h"#include "render_line.h"#include <khtmlview.h>#include <kdebug.h>#include <assert.h>using namespace DOM;using namespace khtml;#define TABLECELLMARGIN -0x4000RenderBox::RenderBox(DOM::NodeImpl* node) : RenderContainer(node){ m_minWidth = -1; m_maxWidth = -1; m_overrideSize = -1; m_width = m_height = 0; m_x = 0; m_y = 0; m_marginTop = 0; m_marginBottom = 0; m_marginLeft = 0; m_marginRight = 0; m_staticX = 0; m_staticY = 0; m_layer = 0; m_inlineBoxWrapper = 0;}void RenderBox::setStyle(RenderStyle *_style){ RenderObject::setStyle(_style); // The root always paints its background/border. if (isRoot()) setShouldPaintBackgroundOrBorder(true); setInline(_style->isDisplayInlineType()); switch(_style->position()) { case ABSOLUTE: case FIXED: setPositioned(true); break; default: setPositioned(false); if (_style->isFloating()) setFloating(true); if (_style->position() == RELATIVE) setRelPositioned(true); } // FIXME: Note that we restrict overflow to blocks for now. One day table bodies and cells // will need to support overflow. // We also deal with the body scroll quirk here, since it sets the scrollbars for the document. if (_style->overflow() != OVISIBLE && isBlockFlow() && !isTableCell() && (!document()->isHTMLDocument() || !isBody())) setHasOverflowClip(); if (requiresLayer()) { if (!m_layer) { m_layer = new (renderArena()) RenderLayer(this); m_layer->insertOnlyThisLayer(); } } else if (m_layer && !isRoot() && !isCanvas()) { m_layer->removeOnlyThisLayer(); m_layer = 0; } if (m_layer) m_layer->styleChanged(); // Set the text color if we're the body. if (isBody()) element()->getDocument()->setTextColor(_style->color()); if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintActionOutline)) static_cast<RenderCanvas*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());}RenderBox::~RenderBox(){ //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;}void RenderBox::detach(){ RenderLayer* layer = m_layer; RenderArena* arena = renderArena(); if (m_inlineBoxWrapper) { if (!documentBeingDestroyed()) m_inlineBoxWrapper->remove(); m_inlineBoxWrapper->detach(arena); m_inlineBoxWrapper = 0; } RenderContainer::detach(); if (layer) layer->detach(arena);}int RenderBox::contentWidth() const{ int w = m_width - borderLeft() - borderRight(); w -= paddingLeft() + paddingRight(); if (includeScrollbarSize()) w -= m_layer->verticalScrollbarWidth(); //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl; return w;}int RenderBox::contentHeight() const{ int h = m_height - borderTop() - borderBottom(); h -= paddingTop() + paddingBottom(); if (includeScrollbarSize()) h -= m_layer->horizontalScrollbarHeight(); return h;}int RenderBox::overrideWidth() const{ return m_overrideSize == -1 ? m_width : m_overrideSize;}int RenderBox::overrideHeight() const{ return m_overrideSize == -1 ? m_height : m_overrideSize;}void RenderBox::setPos( int xPos, int yPos ){ if (xPos == m_x && yPos == m_y) return; // Optimize for the case where we don't move at all. m_x = xPos; m_y = yPos;}int RenderBox::width() const{ return m_width;}int RenderBox::height() const{ return m_height;}// --------------------- painting stuff -------------------------------void RenderBox::paint(PaintInfo& i, int _tx, int _ty){ _tx += m_x; _ty += m_y; // default implementation. Just pass paint through to the children for (RenderObject* child = firstChild(); child; child = child->nextSibling()) child->paint(i, _tx, _ty);}void RenderBox::paintRootBoxDecorations(PaintInfo& i, int _tx, int _ty){ //kdDebug( 6040 ) << renderName() << "::paintBoxDecorations()" << _tx << "/" << _ty << endl; QColor c = style()->backgroundColor(); CachedImage *bg = style()->backgroundImage(); bool canBeTransparent = true; if (!c.isValid() && !bg) { // Locate the <body> element using the DOM. This is easier than trying // to crawl around a render tree with potential :before/:after content and // anonymous blocks created by inline <body> tags etc. We can locate the <body> // render object very easily via the DOM. RenderObject* bodyObject = 0; for (DOM::NodeImpl* elt = element()->firstChild(); elt; elt = elt->nextSibling()) { if (elt->id() == ID_BODY) { bodyObject = elt->renderer(); break; } else if (elt->id() == ID_FRAMESET) { canBeTransparent = false; // Can't scroll a frameset document anyway. break; } } if (bodyObject) { c = bodyObject->style()->backgroundColor(); bg = bodyObject->style()->backgroundImage(); } } // Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with // no background in the child document should show the parent's background. if ((!c.isValid() || qAlpha(c.rgb()) == 0) && canvas()->view()) { bool isTransparent; DOM::NodeImpl* elt = element()->getDocument()->ownerElement(); if (elt) isTransparent = canBeTransparent && elt->id() != ID_FRAME; // Frames are never transparent. else isTransparent = canvas()->view()->isTransparent(); if (isTransparent) canvas()->view()->useSlowRepaints(); // The parent must show behind the child. else c = canvas()->view()->palette().active().color(QColorGroup::Base); } int w = width(); int h = height(); // kdDebug(0) << "width = " << w <<endl; int rw, rh; if (canvas()->view()) { rw = canvas()->view()->contentsWidth(); rh = canvas()->view()->contentsHeight(); } else { rw = canvas()->width(); rh = canvas()->height(); } // kdDebug(0) << "rw = " << rw <<endl; int bx = _tx - marginLeft(); int by = _ty - marginTop(); int bw = kMax(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw); int bh = kMax(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh); // CSS2 14.2: // " The background of the box generated by the root element covers the entire canvas." // hence, paint the background even in the margin areas (unlike for every other element!) // I just love these little inconsistencies .. :-( (Dirk) int my = kMax(by, i.r.y()); paintBackground(i.p, c, bg, my, i.r.height(), bx, by, bw, bh); if (style()->hasBorder() && style()->display() != INLINE) paintBorder( i.p, _tx, _ty, w, h, style() );}void RenderBox::paintBoxDecorations(PaintInfo& i, int _tx, int _ty){ if (!shouldPaintWithinRoot(i)) return; //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl; if (isRoot()) return paintRootBoxDecorations(i, _tx, _ty); int w = width(); int h = height() + borderTopExtra() + borderBottomExtra(); _ty -= borderTopExtra(); int my = kMax(_ty, i.r.y()); int mh; if (_ty < i.r.y()) mh= kMax(0, h - (i.r.y() - _ty)); else mh = kMin(i.r.height(), h); // The <body> only paints its background if the root element has defined a background // independent of the body. Go through the DOM to get to the root element's render object, // since the root could be inline and wrapped in an anonymous block. if (!isBody() || element()->getDocument()->documentElement()->renderer()->style()->backgroundColor().isValid() || element()->getDocument()->documentElement()->renderer()->style()->backgroundImage()) paintBackground(i.p, style()->backgroundColor(), style()->backgroundImage(), my, mh, _tx, _ty, w, h); if (style()->hasBorder()) paintBorder(i.p, _tx, _ty, w, h, style());}void RenderBox::paintBackground(QPainter *p, const QColor &c, CachedImage *bg, int clipy, int cliph, int _tx, int _ty, int w, int height){ paintBackgroundExtended(p, c, bg, clipy, cliph, _tx, _ty, w, height, borderLeft(), borderRight());}void RenderBox::paintBackgroundExtended(QPainter *p, const QColor &c, CachedImage *bg, int clipy, int cliph, int _tx, int _ty, int w, int h, int bleft, int bright){ if (c.isValid() && qAlpha(c.rgb()) > 0) { // If we have an alpha and we are painting the root element, go ahead and blend with our default // background color (typically white). if (qAlpha(c.rgb()) < 0xFF && isRoot() && !canvas()->view()->isTransparent()) p->fillRect(_tx, clipy, w, cliph, canvas()->view()->palette().active().color(QColorGroup::Base)); 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 ) << "painting bgimage at " << _tx << "/" << _ty << endl; // ### might need to add some correct offsets // ### use paddingX/Y // for propagation of <body> up to <html> RenderStyle* sptr = style(); if ((isRoot() && element() && element()->id() == ID_HTML) && firstChild() && !style()->backgroundImage()) sptr = firstChild()->style(); int sx = 0; int sy = 0; int cw,ch; int cx,cy; int vpab = bleft + bright; int hpab = borderTop() + borderBottom(); // CSS2 chapter 14.2.1 if (sptr->backgroundAttachment()) { //scroll int pw = w - vpab; int ph = h - 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; int xPosition = sptr->backgroundXPosition().minWidth(pw-pixw); if (xPosition >= 0) cx = _tx + xPosition; else { cx = _tx; if (pixw == 0) sx = 0; else { sx = -xPosition; cw += xPosition;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -