📄 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.2 2002/01/28 04:31:02 leon Exp $ */// -------------------------------------------------------------------------//#define DEBUG_LAYOUT#include <assert.h>#include "render_interface.h"#include "mgcolor.h"#include "mgpen.h"#include "mgbrush.h"#include "mgsize.h"#include "mgrect.h"#include "mgfontmetrics.h"#include "mgpainter.h"#include "mghtml_part.h"#include "dom_string.h"#include "dom_node.h"#include "dom_textimpl.h"#include "dom_stringimpl.h"#include "dom_exception.h"#include "htmlhashes.h"#include "mghtmlview.h"#include "render_box.h"#include "render_style.h"#include "render_object.h"#include "render_text.h"#include "render_root.h"#include "render_replaced.h"#include "kdebug.h"using namespace DOM;using namespace khtml;RenderBox::RenderBox() : RenderObject(){ 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); switch(style->position()) { case ABSOLUTE: case FIXED: m_positioned = true; break; default: if(style->isFloating()) { m_floating = true; } else { if(style->position() == RELATIVE) {// kdDebug(0) << "set rel pos true" << endl; m_relPositioned = true; } } }}RenderBox::~RenderBox(){ //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;}MGSize RenderBox::contentSize() const{ int w = m_width; int h = m_height; if(m_style->hasBorder()) { w -= borderLeft() + borderRight(); h -= borderTop() + borderBottom(); } if(m_style->hasPadding()) { w -= paddingLeft() + paddingRight(); h -= paddingTop() + paddingBottom(); } return MGSize(w, h);}short RenderBox::contentWidth() const{ short w = m_width;//fprintf(stderr,"render_box w:%d\n",w);//kdDebug( 6040 ) << "RenderBox::contentWidth(1) = " << m_width << endl; if(m_style->hasBorder()) w -= borderLeft() + borderRight(); if(m_style->hasPadding()) w -= paddingLeft() + paddingRight(); //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl;//fprintf(stderr,"---quit render_box w:%d\n",w); return w;}int RenderBox::contentHeight() const{ int h = m_height; if(m_style->hasBorder()) h -= borderTop() + borderBottom(); if(m_style->hasPadding()) h -= paddingTop() + paddingBottom(); return h;}MGSize RenderBox::contentOffset() const{ // ### //int xOff = 0; //int yOff = 0; return MGSize(0, 0);}MGSize RenderBox::paddingSize() const{ return MGSize(0, 0);}MGSize RenderBox::size() const{ return MGSize(0, 0);}short RenderBox::width() const{ return m_width;}int RenderBox::height() const{ return m_height;}// --------------------- printing stuff -------------------------------void RenderBox::print(MGPainter *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 MGPixmap &, const MGRect&, MGCachedImage *image, bool *){ if(image && image->pixmap_size() == image->valid_rect().size()) repaint(); //repaint bg when it finished loading}void RenderBox::printBoxDecorations(MGPainter *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); printBackground(p, m_style->backgroundColor(), m_bgImage, my, mh, _tx, _ty, w, h); if(m_style->hasBorder()) printBorder(p, _tx, _ty, w, h);}void RenderBox::printBackground (MGPainter *p, const MGColor &c, const MGCachedImage *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()) { //kdDebug( 6040 ) << "printing bgimage at " << _tx << "/" << _ty << endl; // ### might need to add some correct offsets // ### use paddingX/Y int sx = 0; int sy = 0; //hacky stuff EBackgroundRepeat bgr = m_style->backgroundRepeat(); bool scroll = m_style->backgroundAttachment(); if ( isHtml() && firstChild() && !m_bgImage ) { bgr = firstChild()->style()->backgroundRepeat(); scroll = firstChild()->style()->backgroundAttachment(); } int cx = _tx; int cy = clipy; int cw = w; int ch = cliph; switch(bgr) { case NO_REPEAT: cw = QMIN(bg->pixmap_size().width(), w); cx = _tx + style()->backgroundXPosition().minWidth((w - cw)/2); /* nobreak */ case REPEAT_X: ch = QMIN(bg->pixmap_size().height(), h); cy = _ty + style()->backgroundYPosition().minWidth((h -ch)/2); break; case REPEAT_Y: cw = QMIN(bg->pixmap_size().width(), w); cx = _tx + style()->backgroundXPosition().minWidth((w - cw)/2); case REPEAT: // make sure that the pixmap is tiled correctly // because we clip the tiling to the visible area (for speed reasons) if(bg->pixmap_size().height() && scroll) sy = (clipy - _ty) % bg->pixmap_size().height(); break; } if( !scroll ) { MGRect r = viewRect(); //kdDebug(0) << "fixed background r.y=" << r.y() << endl; if( isHtml() ) { cy += r.y(); cx += r.x(); } sx = cx - r.x(); sy = cy - r.y(); } p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c), sx, sy); }}void RenderBox::printBorder(MGPainter *p, int _tx, int _ty, int w, int h){ int bottom = _ty + h; int right = _tx + w; right -= (m_style->borderRightWidth() & 1); bottom -= (m_style->borderBottomWidth() & 1); MGColor c; if(m_style->borderTopStyle() != BNONE) { c = m_style->borderTopColor(); if(!c.isValid()) c = m_style->color(); drawBorder(p, _tx, _ty, right, _ty, m_style->borderTopWidth(), BSTop, c, m_style->borderTopStyle()); } if(m_style->borderBottomStyle() != BNONE) { c = m_style->borderBottomColor(); if(!c.isValid()) c = m_style->color(); drawBorder(p, _tx, bottom, right, bottom, m_style->borderBottomWidth(), BSBottom, c, m_style->borderBottomStyle()); } if(m_style->borderLeftStyle() != BNONE) { c = m_style->borderLeftColor(); if(!c.isValid()) c = m_style->color(); drawBorder(p, _tx, _ty, _tx, bottom, m_style->borderLeftWidth(), BSLeft, c, m_style->borderLeftStyle()); } if(m_style->borderRightStyle() != BNONE) { c = m_style->borderRightColor(); if(!c.isValid()) c = m_style->color(); drawBorder(p, right, _ty, right, bottom, m_style->borderRightWidth(), BSRight, c, m_style->borderRightStyle()); }}void RenderBox::outlineBox(MGPainter *p, int _tx, int _ty, const char *color){ p->setPen(MGPen(MGColor(color), 1, MG::DotLine)); p->setBrush( MG::NoBrush ); p->drawRect(_tx, _ty, m_width, m_height);}void RenderBox::close(){ setParsing(false); calcWidth(); calcHeight(); calcMinMaxWidth(); if(containingBlockWidth() < m_minWidth && m_parent) containingBlock()->updateSize(); else if(!isInline() || isReplaced()) { layout(); }}short RenderBox::containingBlockWidth() const{ if (style()->htmlHacks() && style()->flowAroundFloats() && containingBlock()->isFlow() && style()->width().isVariable()) return static_cast<RenderFlow*>(containingBlock())->lineWidth(m_y); else return containingBlock()->contentWidth();}void RenderBox::absolutePosition(int &xPos, int &yPos, bool f){ if ( m_style->position() == FIXED ) f = true; RenderObject *o = container(); if( o ) { o->absolutePosition(xPos, yPos, f); if((!isInline() || isReplaced()) && xPos != -1) xPos += m_x, yPos += m_y; } else xPos = yPos = -1;}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 if (parsing()) { setLayouted(false); containingBlock()->updateHeight(); return; } if(!isInline() || isReplaced()) { int oldHeight = m_height; setLayouted(false); if (hasOverhangingFloats()) { if(containingBlock() != this) containingBlock()->updateHeight(); } layout(); if(m_height != oldHeight) { if(containingBlock() != this) containingBlock()->updateHeight(); } else { containingBlock()->repaint(); } }}void RenderBox::position(int x, int y, int, int, int, bool){ m_x = x + marginLeft(); m_y = y; // ### paddings //m_width = width; /* if( isWidget() ) { int _x = m_x+borderLeft()+paddingLeft(); int _y = m_y+borderTop()+paddingTop(); //static_cast<RenderWidget*>(this)->m_widget->moveWindow( _x, _y ); } */}short RenderBox::verticalPositionHint() const{ switch(m_style->verticalAlign()) { case BASELINE: //kdDebug( 6040 ) << "aligned to baseline" << endl; return contentHeight(); case SUB: // ### case SUPER: // ### case TOP: return PositionTop; case TEXT_TOP:#if 1 return MGFontMetrics(m_style->font(), m_part).ascent();#else return MGFontMetrics(m_style->font(), m_part).descent();#endif case MIDDLE: return contentHeight()/2; case BOTTOM: return PositionBottom; case TEXT_BOTTOM:#if 1 return MGFontMetrics(m_style->font(), m_part).descent();#else return MGFontMetrics(m_style->font(), m_part).ascent();#endif } return 0;}short RenderBox::baselineOffset() const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -