|
|
|
/**
|
|
|
|
* 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("-khtml-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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|