📄 render_list.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) 2003 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. * */#include "render_list.h"#include "rendering/render_canvas.h"#include "xml/dom_docimpl.h"#include "misc/htmltags.h"#include <qpainter.h>#include "misc/helper.h"#include <kdebug.h>//#define BOX_DEBUGusing DOM::DocumentImpl;using namespace khtml;static QString toRoman( int number, bool upper ){ QString roman; QChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' }; QChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' }; QChar *digits = upper ? udigits : ldigits; int i, d = 0; do { int num = number % 10; if ( num % 5 < 4 ) for ( i = num % 5; i > 0; i-- ) roman.insert( 0, digits[ d ] ); if ( num >= 4 && num <= 8) roman.insert( 0, digits[ d+1 ] ); if ( num == 9 ) roman.insert( 0, digits[ d+2 ] ); if ( num % 5 == 4 ) roman.insert( 0, digits[ d ] ); number /= 10; d += 2; } while ( number ); return roman;}static QString toLetter( int number, int base ) { number--; QString letter = (QChar) (base + (number % 26)); // Add a single quote at the end of the alphabet. for (int i = 0; i < (number / 26); i++) { letter += '\''; } return letter;}static QString toHebrew( int number ) { const QChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510}; QString letter; if (number>999) { letter = toHebrew(number/1000) + QString::fromLatin1("'"); number = number%1000; } int hunderts = (number/400); if (hunderts > 0) { for(int i=0; i<hunderts; i++) { letter += QChar(1511 + 3); } } number = number % 400; if ((number / 100) != 0) { letter += QChar (1511 + (number / 100) -1); } number = number % 100; int tens = number/10; if (tens > 0 && !(number == 15 || number == 16)) { letter += tenDigit[tens-1]; } if (number == 15 || number == 16) { // special because of religious letter += QChar(1487 + 9); // reasons letter += QChar(1487 + number - 9); } else { number = number % 10; if (number != 0) { letter += QChar (1487 + number); } } return letter;}// -------------------------------------------------------------------------RenderListItem::RenderListItem(DOM::NodeImpl* node) : RenderBlock(node), _notInList(false){ // init RenderObject attributes setInline(false); // our object is not Inline predefVal = -1; m_marker = 0;}void RenderListItem::setStyle(RenderStyle *_style){ RenderBlock::setStyle(_style); if (style()->listStyleType() != LNONE || (style()->listStyleImage() && !style()->listStyleImage()->isErrorImage())) { RenderStyle *newStyle = new (renderArena()) RenderStyle(); newStyle->ref(); // The marker always inherits from the list item, regardless of where it might end // up (e.g., in some deeply nested line box). See CSS3 spec. newStyle->inheritFrom(style()); if (!m_marker) { m_marker = new (renderArena()) RenderListMarker(document()); m_marker->setStyle(newStyle); m_marker->setListItem(this); _markerInstalledInParent = false; } else m_marker->setStyle(newStyle); newStyle->deref(renderArena()); } else if (m_marker) { m_marker->detach(); m_marker = 0; }}RenderListItem::~RenderListItem(){}void RenderListItem::detach(){ if (m_marker && !_markerInstalledInParent) { m_marker->detach(); m_marker = 0; } RenderBlock::detach();}void RenderListItem::calcListValue(){ // only called from the marker so.. KHTMLAssert(m_marker); if(predefVal != -1) m_marker->m_value = predefVal; else if(!previousSibling()) m_marker->m_value = 1; else { RenderObject *o = previousSibling(); while ( o && (!o->isListItem() || o->style()->listStyleType() == LNONE) ) o = o->previousSibling(); if( o && o->isListItem() && o->style()->listStyleType() != LNONE ) { RenderListItem *item = static_cast<RenderListItem *>(o); m_marker->m_value = item->value() + 1; } else m_marker->m_value = 1; }}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()); _markerInstalledInParent = true; 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();}void RenderListItem::layout( ){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); updateMarkerLocation(); RenderBlock::layout();}void RenderListItem::paint(PaintInfo& i, int _tx, int _ty){ if (!m_height) return;#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << nodeName().string() << "(LI)::paint()" << endl;#endif RenderBlock::paint(i, _tx, _ty);}QRect RenderListItem::getAbsoluteRepaintRect(){ QRect result = RenderBlock::getAbsoluteRepaintRect(); if (m_marker && !m_marker->isInside()) { // This can be a sloppy and imprecise offset as long as it's always too big. int pixHeight = style()->htmlFont().getFontDef().computedPixelSize(); int offset = pixHeight*2/3; int xoff = 0; if (style()->direction() == LTR) xoff = -7 - offset; else xoff = offset; if (m_marker->listImage() && !m_marker->listImage()->isErrorImage()) { // For OUTSIDE bullets shrink back to only a 0.3em margin. 0.67 em is too // much. This brings the margin back to MacIE/Gecko/WinIE levels. // For LTR don't forget to add in the width of the image to the offset as // well (you are moving the image left, so you have to also add in the width // of the image's border box as well). -dwh if (style()->direction() == LTR) xoff -= m_marker->listImage()->pixmap().width() - pixHeight*1/3; else xoff -= pixHeight*1/3; } if (xoff < 0) { result.setX(result.x() + xoff); result.setWidth(result.width() - xoff); } else result.setWidth(result.width() + xoff); } return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -