📄 render_list.cpp
字号:
/** * This file is part of the HTML rendering engine for KDE. * * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000-2002 Dirk Mueller (mueller@kde.org) * (C) 2003 Apple Computer, Inc. * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) * * 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_list.h"#include "rendering/render_canvas.h"#include "rendering/enumerate.h"#include "rendering/counter_tree.h"#include "html/html_listimpl.h"#include "misc/helper.h"#include "misc/htmltags.h"#include "misc/loader.h"#include "xml/dom_docimpl.h"#include <kdebug.h>#include <kglobal.h>#include <qvaluelist.h>//#define BOX_DEBUGusing namespace khtml;using namespace Enumerate;const int cMarkerPadding = 7;// -------------------------------------------------------------------------RenderListItem::RenderListItem(DOM::NodeImpl* node) : RenderBlock(node){ // init RenderObject attributes setInline(false); // our object is not Inline predefVal = -1; m_marker = 0; m_counter = 0; m_insideList = false; m_deleteMarker = false;}void RenderListItem::setStyle(RenderStyle *_style){ RenderBlock::setStyle(_style); RenderStyle *newStyle = new RenderStyle(); newStyle->ref(); newStyle->inheritFrom(style()); if(!m_marker && style()->listStyleType() != LNONE) { m_marker = new (renderArena()) RenderListMarker(element()); m_marker->setIsAnonymous( true ); m_marker->setStyle(newStyle); m_marker->setListItem( this ); m_deleteMarker = true; } else if ( m_marker && style()->listStyleType() == LNONE) { m_marker->detach(); m_marker = 0; } else if ( m_marker ) { m_marker->setStyle(newStyle); } newStyle->deref();}void RenderListItem::detach(){ if ( m_marker && m_deleteMarker ) m_marker->detach(); RenderBlock::detach();}static RenderObject* getParentOfFirstLineBox(RenderObject* curr, RenderObject* marker){ RenderObject* firstChild = curr->firstChild(); if (!firstChild) return 0; for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { if (currChild == marker) continue; if (currChild->isInline()) return curr; if (currChild->isFloating() || currChild->isPositioned()) continue; if (currChild->isTable() || !currChild->isRenderBlock()) break; if (currChild->style()->htmlHacks() && currChild->element() && (currChild->element()->id() == ID_UL || currChild->element()->id() == ID_OL)) break; RenderObject* lineBox = getParentOfFirstLineBox(currChild, marker); if (lineBox) return lineBox; } return 0;}void RenderListItem::updateMarkerLocation(){ // Sanity check the location of our marker. if (m_marker) { RenderObject* markerPar = m_marker->parent(); RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); if (!lineBoxParent) { // If the marker is currently contained inside an anonymous box, // then we are the only item in that anonymous box (since no line box // parent was found). It's ok to just leave the marker where it is // in this case. if (markerPar && markerPar->isAnonymousBlock()) lineBoxParent = markerPar; else lineBoxParent = this; } if (markerPar != lineBoxParent) { if (markerPar) markerPar->removeChild(m_marker); if (!lineBoxParent) lineBoxParent = this; lineBoxParent->addChild(m_marker, lineBoxParent->firstChild()); m_deleteMarker = false; if (!m_marker->minMaxKnown()) m_marker->calcMinMaxWidth(); recalcMinMaxWidths(); } }}void RenderListItem::calcMinMaxWidth(){ // Make sure our marker is in the correct location. updateMarkerLocation(); if (!minMaxKnown()) RenderBlock::calcMinMaxWidth();}/*short RenderListItem::marginLeft() const{ if (m_insideList) return RenderBlock::marginLeft(); else return kMax(m_marker->markerWidth(), RenderBlock::marginLeft());}short RenderListItem::marginRight() const{ return RenderBlock::marginRight();}*/void RenderListItem::layout( ){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); updateMarkerLocation(); RenderBlock::layout();}// -----------------------------------------------------------RenderListMarker::RenderListMarker(DOM::NodeImpl* node) : RenderBox(node), m_listImage(0), m_markerWidth(0){ // init RenderObject attributes setInline(true); // our object is Inline setReplaced(true); // pretend to be replaced // val = -1; // m_listImage = 0;}RenderListMarker::~RenderListMarker(){ if(m_listImage) m_listImage->deref(this);}void RenderListMarker::setStyle(RenderStyle *s){ if ( s && style() && s->listStylePosition() != style()->listStylePosition() ) setNeedsLayoutAndMinMaxRecalc(); RenderBox::setStyle(s); if ( m_listImage != style()->listStyleImage() ) { if(m_listImage) m_listImage->deref(this); m_listImage = style()->listStyleImage(); if(m_listImage) m_listImage->ref(this); }}void RenderListMarker::paint(PaintInfo& paintInfo, int _tx, int _ty){ if (paintInfo.phase != PaintActionForeground) return; if (style()->visibility() != VISIBLE) return; _tx += m_x; _ty += m_y; if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top())) return; if(shouldPaintBackgroundOrBorder()) paintBoxDecorations(paintInfo, _tx, _ty); QPainter* p = paintInfo.p;#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << nodeName().string() << "(ListMarker)::paintObject(" << _tx << ", " << _ty << ")" << endl;#endif p->setFont(style()->font()); const QFontMetrics fm = p->fontMetrics(); // The marker needs to adjust its tx, for the case where it's an outside marker. RenderObject* listItem = 0; int leftLineOffset = 0; int rightLineOffset = 0; if (!listPositionInside()) { listItem = this; int yOffset = 0; int xOffset = 0; while (listItem && listItem != m_listItem) { yOffset += listItem->yPos(); xOffset += listItem->xPos(); listItem = listItem->parent(); } // Now that we have our xoffset within the listbox, we need to adjust ourselves by the delta // between our current xoffset and our desired position (which is just outside the border box // of the list item). if (style()->direction() == LTR) { leftLineOffset = m_listItem->leftRelOffset(yOffset, m_listItem->leftOffset(yOffset)); _tx -= (xOffset - leftLineOffset) + m_listItem->paddingLeft() + m_listItem->borderLeft(); } else { rightLineOffset = m_listItem->rightRelOffset(yOffset, m_listItem->rightOffset(yOffset)); _tx += (rightLineOffset-xOffset) + m_listItem->paddingRight() + m_listItem->borderRight(); } } int offset = fm.ascent()*2/3; bool haveImage = m_listImage && !m_listImage->isErrorImage(); if (haveImage) offset = m_listImage->pixmap().width(); int xoff = 0; int yoff = fm.ascent() - offset; int bulletWidth = offset/2; if (offset%2) bulletWidth++; if (!listPositionInside()) { if (listItem->style()->direction() == LTR) xoff = -cMarkerPadding - offset; else xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth)); } else if (style()->direction() == RTL) xoff += haveImage ? cMarkerPadding : (m_width - bulletWidth); if ( m_listImage && !m_listImage->isErrorImage()) { p->drawPixmap( QPoint( _tx + xoff, _ty ), m_listImage->pixmap()); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -