/** * This file is part of the HTML rendering engine for KDE. * * Copyright (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_generated.h" #include "rendering/render_style.h" #include "rendering/enumerate.h" #include "rendering/counter_tree.h" #include "css/css_valueimpl.h" using namespace tdehtml; using namespace Enumerate; // ------------------------------------------------------------------------- RenderCounterBase::RenderCounterBase(DOM::NodeImpl* node) : RenderText(node,0), m_counterNode(0) { } void RenderCounterBase::layout() { TDEHTMLAssert( needsLayout() ); if ( !minMaxKnown() ) calcMinMaxWidth(); RenderText::layout(); } void RenderCounterBase::calcMinMaxWidth() { TDEHTMLAssert( !minMaxKnown() ); generateContent(); if (str) str->deref(); str = new DOM::DOMStringImpl(m_item.unicode(), m_item.length()); str->ref(); RenderText::calcMinMaxWidth(); } void RenderCounterBase::updateContent() { setMinMaxKnown(false); } // ------------------------------------------------------------------------- RenderCounter::RenderCounter(DOM::NodeImpl* node, const DOM::CounterImpl* counter) : RenderCounterBase(node), m_counter(counter) { } TQString RenderCounter::toListStyleType(int value, int total, EListStyleType type) { TQString item; switch(type) { case LNONE: break; // Glyphs: (these values are not really used and instead handled by RenderGlyph) case LDISC: item = TQChar(0x2022); break; case LCIRCLE: item = TQChar(0x25e6); break; case LSQUARE: item = TQChar(0x25a0); break; case LBOX: item = TQChar(0x25a1); break; case LDIAMOND: item = TQChar(0x25c6); break; // Numeric: case LDECIMAL: item.setNum ( value ); break; case DECIMAL_LEADING_ZERO: { int decimals = 2; int t = total/100; while (t>0) { t = t/10; decimals++; } decimals = kMax(decimals, 2); TQString num = TQString::number(value); item.fill('0',decimals-num.length()); item.append(num); break; } case ARABIC_INDIC: item = toArabicIndic( value ); break; case LAO: item = toLao( value ); break; case PERSIAN: case URDU: item = toPersianUrdu( value ); break; case THAI: item = toThai( value ); break; case TIBETAN: item = toTibetan( value ); break; // Algoritmic: case LOWER_ROMAN: item = toRoman( value, false ); break; case UPPER_ROMAN: item = toRoman( value, true ); break; case HEBREW: item = toHebrew( value ); break; case ARMENIAN: item = toArmenian( value ); break; case GEORGIAN: item = toGeorgian( value ); break; // Alphabetic: case LOWER_ALPHA: case LOWER_LATIN: item = toLowerLatin( value ); break; case UPPER_ALPHA: case UPPER_LATIN: item = toUpperLatin( value ); break; case LOWER_GREEK: item = toLowerGreek( value ); break; case UPPER_GREEK: item = toUpperGreek( value ); break; case HIRAGANA: item = toHiragana( value ); break; case HIRAGANA_IROHA: item = toHiraganaIroha( value ); break; case KATAKANA: item = toKatakana( value ); break; case KATAKANA_IROHA: item = toKatakanaIroha( value ); break; // Ideographic: case JAPANESE_FORMAL: item = toJapaneseFormal( value ); break; case JAPANESE_INFORMAL: item = toJapaneseInformal( value ); break; case SIMP_CHINESE_FORMAL: item = toSimpChineseFormal( value ); break; case SIMP_CHINESE_INFORMAL: item = toSimpChineseInformal( value ); break; case TRAD_CHINESE_FORMAL: item = toTradChineseFormal( value ); break; case CJK_IDEOGRAPHIC: // CSS 3 List says treat as trad-chinese-informal case TRAD_CHINESE_INFORMAL: item = toTradChineseInformal( value ); break; default: item.setNum ( value ); break; } return item; } void RenderCounter::generateContent() { bool counters; counters = !m_counter->separator().isNull(); if (!m_counterNode) m_counterNode = getCounter(m_counter->identifier().string(), true, counters); int value = m_counterNode->count(); if (m_counterNode->isReset()) value = m_counterNode->value(); int total = value; if (m_counterNode->parent()) total = m_counterNode->parent()->total(); m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle()); if (counters) { CounterNode *counter = m_counterNode->parent(); // we deliberately do not render the root counter-node while(counter->parent() && !(counter->isReset() && counter->parent()->isRoot())) { value = counter->count(); total = counter->parent()->total(); m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle()) + m_counter->separator().string() + m_item; counter = counter->parent(); }; } } // ------------------------------------------------------------------------- RenderQuote::RenderQuote(DOM::NodeImpl* node, EQuoteContent type) : RenderCounterBase(node), m_quoteType(type) { } int RenderQuote::quoteCount() const { switch(m_quoteType) { case OPEN_QUOTE: case NO_OPEN_QUOTE: return 1; case CLOSE_QUOTE: case NO_CLOSE_QUOTE: return -1; case NO_QUOTE: return 0; } assert(false); return 0; } void RenderQuote::generateContent() { bool visual; if (m_quoteType == NO_CLOSE_QUOTE || m_quoteType == NO_OPEN_QUOTE) visual = false; else visual = true; if (!m_counterNode) m_counterNode = getCounter("-tdehtml-quotes", visual, false); int value = m_counterNode->count(); if (m_counterNode->isReset()) value = m_counterNode->value(); switch (m_quoteType) { case OPEN_QUOTE: m_item = style()->openQuote( value ); break; case CLOSE_QUOTE: m_item = style()->closeQuote( value ); break; case NO_OPEN_QUOTE: case NO_CLOSE_QUOTE: case NO_QUOTE: m_item = TQString(); } } // ------------------------------------------------------------------------- RenderGlyph::RenderGlyph(DOM::NodeImpl* node, EListStyleType type) : RenderBox(node), m_type(type) { setInline(true); // setReplaced(true); } void RenderGlyph::setStyle(RenderStyle *_style) { RenderBox::setStyle(_style); const TQFontMetrics &fm = style()->fontMetrics(); TQRect xSize= fm.boundingRect('x'); m_height = xSize.height(); m_width = xSize.width();; switch(m_type) { // Glyphs: case LDISC: case LCIRCLE: case LSQUARE: case LBOX: case LDIAMOND: case LNONE: break; default: // not a glyph ! assert(false); break; } } void RenderGlyph::calcMinMaxWidth() { m_minWidth = m_width; m_maxWidth = m_width; setMinMaxKnown(); } short RenderGlyph::lineHeight(bool /*b*/) const { return height(); } short RenderGlyph::baselinePosition(bool /*b*/) const { return height(); } void RenderGlyph::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; TQPainter* p = paintInfo.p; const TQColor color( style()->color() ); p->setPen( color ); int xHeight = m_height; int bulletWidth = (xHeight+1)/2; int yoff = (xHeight - 1)/4; TQRect marker(_tx, _ty + yoff, bulletWidth, bulletWidth); switch(m_type) { case LDISC: p->setBrush( color ); p->drawEllipse( marker ); return; case LCIRCLE: p->setBrush( Qt::NoBrush ); p->drawEllipse( marker ); return; case LSQUARE: p->setBrush( color ); p->drawRect( marker ); return; case LBOX: p->setBrush( Qt::NoBrush ); p->drawRect( marker ); return; case LDIAMOND: { static TQPointArray diamond(4); int x = marker.x(); int y = marker.y(); int s = bulletWidth/2; diamond[0] = TQPoint(x+s, y); diamond[1] = TQPoint(x+2*s, y+s); diamond[2] = TQPoint(x+s, y+2*s); diamond[3] = TQPoint(x, y+s); p->setBrush( color ); p->drawConvexPolygon( diamond, 0, 4 ); return; } case LNONE: return; default: // not a glyph assert(false); } }