diff options
Diffstat (limited to 'lib/kformula/elementtype.cpp')
-rw-r--r-- | lib/kformula/elementtype.cpp | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/lib/kformula/elementtype.cpp b/lib/kformula/elementtype.cpp new file mode 100644 index 000000000..bd2c33738 --- /dev/null +++ b/lib/kformula/elementtype.cpp @@ -0,0 +1,765 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org> + Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de> + + 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 <tqfont.h> +#include <tqfontmetrics.h> +#include <tqpainter.h> + +#include <kdebug.h> + +#include "basicelement.h" +#include "contextstyle.h" +#include "elementtype.h" +#include "sequenceelement.h" +#include "sequenceparser.h" +#include "textelement.h" + + +KFORMULA_NAMESPACE_BEGIN + +int ElementType::evilDestructionCount = 0; + +/* + * Converts CharStyle and CharFamily to the MathML 'mathvariant' + * attribute (see MathML spec 3.2.2). + */ +TQString format2variant( CharStyle style, CharFamily family ) +{ + TQString result; + + switch( family ) { + case normalFamily: + case anyFamily: + switch( style ) { + case normalChar: + result = "normal"; break; + case boldChar: + result = "bold"; break; + case italicChar: + result = "italic"; break; + case boldItalicChar: + result = "bold-italic"; break; + case anyChar: + break; + } + break; + case scriptFamily: + result = "script"; + if ( style == boldChar || style == boldItalicChar ) + result = "bold-" + result; + break; + case frakturFamily: + result = "fraktur"; + if ( style == boldChar || style == boldItalicChar ) + result = "bold-" + result; + break; + case doubleStruckFamily: + result = "double-struck"; break; + } + + return result; +} + +ElementType::ElementType( SequenceParser* parser ) + : from( parser->getStart() ), to( parser->getEnd() ), prev( 0 ) +{ + evilDestructionCount++; +} + +ElementType::~ElementType() +{ + delete prev; + evilDestructionCount--; +} + + +TQString ElementType::text( SequenceElement* seq ) const +{ + TQString str; + for ( uint i=start(); i<end(); ++i ) { + str.append( seq->getChild( i )->getCharacter() ); + } + return str; +} + + +luPt ElementType::getSpaceBefore( const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( MultiElementType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( OperatorType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( RelationType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( PunctuationType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( BracketType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( ComplexElementType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::getSpaceAfter( InnerElementType*, + const ContextStyle&, + ContextStyle::TextStyle, + double ) +{ + return 0; +} + +luPt ElementType::thinSpaceIfNotScript( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( !context.isScript( tstyle ) ) { + return context.getThinSpace( tstyle, factor ); + } + return 0; +} + +luPt ElementType::mediumSpaceIfNotScript( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( !context.isScript( tstyle ) ) { + return context.getMediumSpace( tstyle, factor ); + } + return 0; +} + +luPt ElementType::thickSpaceIfNotScript( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( !context.isScript( tstyle ) ) { + return context.getThickSpace( tstyle, factor ); + } + return 0; +} + + +TQFont ElementType::getFont(const ContextStyle& context) +{ + return context.getDefaultFont(); +} + +void ElementType::setUpPainter(const ContextStyle& context, TQPainter& painter) +{ + painter.setPen(context.getDefaultColor()); +} + +void ElementType::append( ElementType* element ) +{ + element->prev = this; +} + +void ElementType::output() +{ + kdDebug( DEBUGID ) << start() << " - " << end() << endl; +} + +void ElementType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat ) +{ + for ( uint i = from; i < to; ++i ) { + se->getChild( i )->writeMathML( doc, de, oasisFormat ); + } +} + + +SequenceType::SequenceType( SequenceParser* parser ) + : ElementType( parser ), last( 0 ) +{ + while ( true ) { + parser->nextToken(); + //cerr << "SequenceType::SequenceType(): " << parser->getTokenType() << " " + // << parser->getStart() << " " << parser->getEnd() << endl; + if ( parser->getTokenType() == END ) { + break; + } + ElementType* nextType = parser->getPrimitive(); + if ( nextType == 0 ) { + break; + } + if ( last != 0 ) { + last->append( nextType ); + } + last = nextType; + } +} + +SequenceType::~SequenceType() +{ + delete last; +} + + +void SequenceType::output() +{ +} + + +MultiElementType::MultiElementType( SequenceParser* parser ) + : ElementType( parser ) +{ + for ( uint i = start(); i < end(); i++ ) { + parser->setElementType( i, this ); + } + m_text = parser->text(); +} + + +luPt MultiElementType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt MultiElementType::getSpaceAfter( OperatorType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt MultiElementType::getSpaceAfter( RelationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt MultiElementType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + + +TextType::TextType( SequenceParser* parser ) + : MultiElementType( parser ) +{ +} + +void TextType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat ) +{ + for ( uint i = start(); i < end(); ++i ) { + TQDomElement text = doc.createElement( oasisFormat ? "math:mi" : "mi" ); + BasicElement* be = se->getChild( i ); + TextElement* te = static_cast<TextElement*>( be ); + TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily()); + if ( !mathvariant.isNull() ) + text.setAttribute( "mathvariant", mathvariant ); + + text.appendChild( doc.createTextNode( be->getCharacter() ) ); + + de.appendChild( text ); + if ( i != end() - 1 ) { + TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" ); + op.appendChild( doc.createEntityReference( "InvisibleTimes" ) ); + de.appendChild( op ); + } + } +} + + +NameType::NameType( SequenceParser* parser ) + : MultiElementType( parser ) +{ +} + +void NameType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat ) +{ + se->getChild( start() )->writeMathML( doc, de, oasisFormat ); + + /* + TQDomElement name = doc.createElement( "mi" ); + TQString value; + for ( uint i = start(); i < end(); ++i ) { + BasicElement* be = se->getChild( i ); + //TextElement* te = static_cast<TextElement*>( be ); + value += be->getCharacter(); + } + name.appendChild( doc.createTextNode( value ) ); + de.appendChild( name );*/ +} + + +TQFont NameType::getFont(const ContextStyle& context) +{ + return context.getNameFont(); +} + +NumberType::NumberType( SequenceParser* parser ) + : MultiElementType( parser ) +{ +} + +TQFont NumberType::getFont(const ContextStyle& context) +{ + return context.getNumberFont(); +} + +void NumberType::setUpPainter(const ContextStyle& context, TQPainter& painter) +{ + painter.setPen(context.getNumberColor()); +} + +void NumberType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat ) +{ + TQDomElement name = doc.createElement( oasisFormat ? "math:mn" : "mn" ); + TQString value; + for ( uint i = start(); i < end(); ++i ) { + BasicElement* be = se->getChild( i ); + value += be->getCharacter(); + } + TextElement* te = static_cast<TextElement*>( se->getChild( start() ) ); + TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() ); + if ( !mathvariant.isNull() ) + name.setAttribute( "mathvariant", mathvariant ); + + name.appendChild( doc.createTextNode( value ) ); + de.appendChild( name ); +} + + +SingleElementType::SingleElementType( SequenceParser* parser ) + : ElementType( parser ) +{ + parser->setElementType( start(), this ); +} + +AbstractOperatorType::AbstractOperatorType( SequenceParser* parser ) + : SingleElementType( parser ) +{ +} + +void AbstractOperatorType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat ) +{ + TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" ); + BasicElement* be = se->getChild( start() ); + if ( be->getCharacter().latin1() != 0 ) { + // latin-1 char + op.appendChild( doc.createTextNode( be->getCharacter() ) ); + } + else { + // unicode char + TQString s; + op.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) ); + } + TextElement* te = static_cast<TextElement*>( be ); + TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() ); + if ( !mathvariant.isNull() ) + op.setAttribute( "mathvariant", mathvariant ); + + de.appendChild( op ); +} + +OperatorType::OperatorType( SequenceParser* parser ) + : AbstractOperatorType( parser ) +{ +} + +luPt OperatorType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt OperatorType::getSpaceAfter( MultiElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt OperatorType::getSpaceAfter( BracketType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt OperatorType::getSpaceAfter( ComplexElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt OperatorType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + + +TQFont OperatorType::getFont(const ContextStyle& context) +{ + return context.getOperatorFont(); +} + +void OperatorType::setUpPainter(const ContextStyle& context, TQPainter& painter) +{ + painter.setPen(context.getOperatorColor()); +} + + +RelationType::RelationType( SequenceParser* parser ) + : AbstractOperatorType( parser ) +{ +} + +luPt RelationType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt RelationType::getSpaceAfter( MultiElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt RelationType::getSpaceAfter( BracketType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt RelationType::getSpaceAfter( ComplexElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt RelationType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +TQFont RelationType::getFont( const ContextStyle& context ) +{ + return context.getOperatorFont(); +} + +void RelationType::setUpPainter( const ContextStyle& context, TQPainter& painter ) +{ + painter.setPen(context.getOperatorColor()); +} + + + +PunctuationType::PunctuationType( SequenceParser* parser ) + : AbstractOperatorType( parser ) +{ +} + +luPt PunctuationType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt PunctuationType::getSpaceAfter( MultiElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt PunctuationType::getSpaceAfter( RelationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt PunctuationType::getSpaceAfter( PunctuationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt PunctuationType::getSpaceAfter( BracketType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt PunctuationType::getSpaceAfter( ComplexElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt PunctuationType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +TQFont PunctuationType::getFont( const ContextStyle& context ) +{ + return context.getOperatorFont(); +} + +void PunctuationType::setUpPainter( const ContextStyle& context, TQPainter& painter ) +{ + painter.setPen( context.getDefaultColor() ); +} + + +BracketType::BracketType( SequenceParser* parser ) + : SingleElementType( parser ) +{ +} + +luPt BracketType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt BracketType::getSpaceAfter( OperatorType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt BracketType::getSpaceAfter( RelationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt BracketType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + + +ComplexElementType::ComplexElementType( SequenceParser* parser ) + : SingleElementType( parser ) +{ +} + +luPt ComplexElementType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt ComplexElementType::getSpaceAfter( OperatorType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt ComplexElementType::getSpaceAfter( RelationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt ComplexElementType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + + +InnerElementType::InnerElementType( SequenceParser* parser ) + : SingleElementType( parser ) +{ +} + +luPt InnerElementType::getSpaceBefore( const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + if ( getPrev() != 0 ) { + return getPrev()->getSpaceAfter( this, context, tstyle, factor ); + } + return 0; +} + +luPt InnerElementType::getSpaceAfter( MultiElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( OperatorType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return mediumSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( RelationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thickSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( PunctuationType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( BracketType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( ComplexElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + +luPt InnerElementType::getSpaceAfter( InnerElementType*, + const ContextStyle& context, + ContextStyle::TextStyle tstyle, + double factor ) +{ + return thinSpaceIfNotScript( context, tstyle, factor ); +} + + +KFORMULA_NAMESPACE_END |